Skip to main content

Context Providers

Why

A common agent shape: “answer using these N markdown docs / this DB row / today’s status feed”. You can do that with tools (the LLM calls fetch_status() whenever it needs the data), but for context that the LLM always needs, tools are wasteful:
  • An extra round-trip per turn.
  • The LLM might forget to call.
  • Tool definitions take prompt space.
The alternative: pre-fetch the context and inject it into the system prompt before the model sees the user’s message. That’s what a ContextProvider does.

ContextProvider interface

The framework wraps your return value as:
Tags help the model distinguish multiple sources.

Built-in providers

FilesystemContextProvider

Reads every file matching glob under basePath, concatenates them, returns the result. Files over maxFileSize are skipped. Total file count capped at maxFiles. Each file is prefixed with # <relative path> so the model knows what came from where. Use for: project README, design docs, prompt templates loaded from disk, user-uploaded notes.

HttpContextProvider

Fetches the URL on every fetch() call unless cacheTtlMs > 0, in which case the result is cached for that many milliseconds. If the request fails (network error, non-2xx), the provider returns null and silently continues. No retries (wrap with your own if you need them). Use for: status feeds, configuration endpoints, “latest pricing” data.

DatabaseContextProvider

Thin wrapper that just adapts an arbitrary async function to the ContextProvider interface, with the name used for the <context> tag. Use for: anything that’s not a file or HTTP endpoint — DBs, cache, in-process Maps, custom APIs.

Plugging into an Agent

(Direct integration into the Agent’s instructions resolver is on the roadmap; for now, fetch the context and inject it yourself.)

resolveContextProviders(providers, query, ctx)

The helper that runs all providers in parallel and concatenates their outputs.
  • Runs fetch() on every provider in parallel via Promise.allSettled.
  • Skips providers that throw or return null.
  • Wraps each non-null result in <context name="...">...</context>.
  • Returns the joined string (or "" if nothing returned).
If you need different orchestration (sequential, with-deadline, cancellable), drive the providers yourself.

Caching strategies

HttpContextProvider has built-in TTL caching. For the others, layer it yourself:
Or just memoize at the orchestrator level.

Per-user context

ctx carries userId, tenantId, sessionState. Use them inside fetch() to personalize:
The provider gets the same RunContext that the agent sees, so any state you’ve stashed via RunContext.sessionState is available.

Token cost considerations

Context is paid for on every turn. A 50KB markdown corpus injected into the system prompt costs ~$0.03 per turn at GPT-4o pricing.
  • Always-on, small: context provider is the right choice.
  • Sometimes-on, large: use a tool (searchNotes) or RAG retrieval instead.
  • Always-on, large: consider prompt caching (Anthropic’s cache_control, OpenAI’s prompt_caching) — Agentium honors both when the underlying provider supports them.

See also

  • Prompts and Instructions — how the resolved context gets composed into the system message
  • GraphRAG — when “context” is a graph query
  • Skills — the skill system is itself a kind of context provider (with extra structure)