Skip to content

Providers

Talon decouples agent execution from any specific SDK or CLI through a provider abstraction layer. The daemon resolves which provider to use from config, independently for foreground and background agents. You can mix providers across personas and assign different providers to different workloads.

Four providers ship out of the box:

ProviderStrategySession resumptionContext windowPrerequisites
claude-codeSDK + CLIYes200k tokensClaude Code CLI, authenticated
gemini-cliCLINo1M tokensGemini CLI, authenticated
codex-cliCLIYes400k tokensCodex CLI (codex auth)
openai-compatibleWrapper CLINoConfigurableAny OpenAI-compatible endpoint

Claude Code (default) runs via the Anthropic Agent SDK for foreground sessions and the Claude Code CLI for background agents. Sessions resume across messages on the same thread.

Gemini CLI runs entirely through CLI invocation. Each run is independent — no session state persists between messages. The 1M token context window makes it well-suited for large document analysis.

Codex CLI runs via the OpenAI Codex CLI. Foreground threads are resumable like Claude Code, and as of PR #176 Talon now surfaces incremental assistant text and structured tool activity during foreground Codex runs instead of waiting for one final blob of output. Background Codex runs are still ephemeral. Use options.defaultModel to set the model.

OpenAI-compatible is an experimental wrapper-backed provider for endpoints that speak the OpenAI chat API. That includes Ollama, Ollama Cloud, vLLM, Groq-compatible gateways, and similar services. It does not support session resumption, but it does support Talon’s existing tool path, context rotation, and background-worker routing.

Configure providers under agentRunner.providers (foreground) and backgroundAgent.providers (background workers). Only the providers you configure are available.

agentRunner:
defaultProvider: claude-code
providers:
claude-code:
enabled: true
command: claude
contextWindowTokens: 200000
contextManagement:
enabled: true
triggerMetric: cache_read_input_tokens
thresholdRatio: 0.5
recentMessageCount: 10
summarizer: session-summarizer
codex-cli:
enabled: false
command: codex
contextWindowTokens: 400000
contextManagement:
enabled: true
triggerMetric: cache_read_input_tokens
thresholdRatio: 0.8
recentMessageCount: 10
summarizer: session-summarizer
options:
defaultModel: gpt-5.4
openai-compatible:
enabled: false
command: node
contextWindowTokens: 256000
contextManagement:
enabled: true
triggerMetric: input_tokens
thresholdRatio: 0.75
recentMessageCount: 10
summarizer: session-summarizer
options:
baseUrl: http://127.0.0.1:11434/v1
defaultModel: qwen3-coder:30b
providerId: ollama
gemini-cli:
enabled: false
command: gemini
contextWindowTokens: 1000000
backgroundAgent:
enabled: true
maxConcurrent: 3
defaultProvider: claude-code
providers:
claude-code:
enabled: true
command: claude
contextWindowTokens: 200000
codex-cli:
enabled: false
command: codex
contextWindowTokens: 400000
options:
defaultModel: gpt-5.4
openai-compatible:
enabled: false
command: node
contextWindowTokens: 256000
options:
baseUrl: http://127.0.0.1:11434/v1
defaultModel: qwen3-coder:30b
providerId: ollama
FieldDescription
defaultProviderProvider used when no per-persona override is set
providers.<name>.enabledEnable or disable this provider
providers.<name>.commandRuntime command to invoke (claude, gemini, codex, or node for openai-compatible)
providers.<name>.contextWindowTokensContext window size for rotation calculations
providers.<name>.optionsProvider-specific options (for example defaultModel for codex-cli, or baseUrl / providerId for openai-compatible)

The openai-compatible provider gives Talon a generic path to any endpoint that implements the OpenAI chat API. The most obvious use case is Ollama or Ollama Cloud, but the same pattern works for other compatible gateways as long as they expose the expected API surface.

Minimal foreground configuration:

agentRunner:
defaultProvider: openai-compatible
providers:
openai-compatible:
enabled: true
command: node
contextWindowTokens: 256000
contextManagement:
enabled: true
triggerMetric: input_tokens
thresholdRatio: 0.75
recentMessageCount: 10
summarizer: session-observer
options:
baseUrl: ${OLLAMA_BASE_URL}
defaultModel: glm-5.1
providerId: ollama
auth:
providers:
ollama:
apiKey: ${OLLAMA_API_KEY}
baseURL: ${OLLAMA_BASE_URL}

Notes:

  • command: node is expected. Talon launches its bundled wrapper under Node for this provider.
  • options.baseUrl points at the OpenAI-compatible endpoint, usually ending in /v1.
  • options.defaultModel is the model Talon should request if the persona does not override model.
  • options.providerId tells Talon which auth.providers.<name> slot to read first.
  • If auth.providers.<options.providerId> is absent, Talon falls back to auth.providers.openai-compatible.

openai-compatible can expose the same context-rotation metrics as the other providers, but only if the upstream server reports prompt-cache usage. OpenAI, DeepSeek, GLM, and some vLLM deployments do. Ollama does not currently surface those cache counts through its OpenAI-compatible usage object.

For that reason:

  • use triggerMetric: cache_read_input_tokens only when the upstream actually reports cached token counts
  • use triggerMetric: input_tokens for Ollama or any compatible server that does not

openai-compatible can be used under backgroundAgent.providers the same way as other providers. Background runs do not stream tool events back to the user live, but they use the same tool bridge and capability filtering as the foreground path.

The openai-compatible provider automatically excerpts large tool outputs before they enter the agent’s message history. This prevents a single oversized result — a directory listing with thousands of files, a read_file dump of a large log, or verbose command output — from overflowing the context window in one step.

How it works:

  • When a tool returns output that exceeds the configured cap, the wrapper replaces it with a head-and-tail excerpt and a TRUNCATED BY TALON marker. The marker includes the toolCallId and tells the model it can retrieve the full output on demand.
  • The complete payload is retained in an in-memory store for the duration of the current agent run. It is not persisted to disk or the database.
  • Errors are never truncated — they pass through verbatim because they are typically short and critical.
  • Shape-aware handling preserves MCP { content: [{ type: 'text', text }] } envelopes when the bulk of the payload is in text parts. Plain strings and objects are handled safely without bypassing the cap.

The fetch_tool_output tool:

A synthetic fetch_tool_output tool is automatically registered during each run. If the model needs content that was trimmed, it can call this tool with the original toolCallId and a character range:

# The model can request:
# fetch_tool_output(toolCallId: "abc123", startChar: 0, endChar: 8000)

Each slice is itself capped at 8,000 characters to prevent the model from reintroducing the full payload in a single request.

Configuration:

Set options.toolOutputCap under the openai-compatible provider block. The value is in characters.

OptionDefaultDescription
toolOutputCap4000Maximum characters of a single tool result allowed into message history. Set to 0 to disable excerpting entirely.

Example configuration for an Ollama endpoint with a small context window:

agentRunner:
defaultProvider: openai-compatible
providers:
openai-compatible:
enabled: true
command: node
contextWindowTokens: 32000
contextManagement:
enabled: true
triggerMetric: input_tokens
thresholdRatio: 0.75
recentMessageCount: 10
summarizer: session-observer
options:
baseUrl: http://127.0.0.1:11434/v1
defaultModel: qwen3-coder:30b
providerId: ollama
toolOutputCap: 4000

:::note Provider scope Tool output excerpting applies only to the openai-compatible provider. Claude Code, Codex CLI, and Gemini CLI manage their own tool loops internally, so Talon cannot intercept and trim their outputs. :::

Set the provider field on any persona to override the default:

personas:
- name: assistant
model: claude-sonnet-4-6
provider: claude-code # interactive Claude persona
- name: coder
model: gpt-5.4
provider: codex-cli # OpenAI-powered coding persona
- name: local-researcher
model: glm-5.1
provider: openai-compatible # Ollama / OpenAI-compatible endpoint
- name: analyst
model: gemini-2.0-flash
provider: gemini-cli # large-context analysis persona

A2A delegation always runs the target persona on its own configured provider, regardless of which provider the source thread is using.

Actually, model and provider need to make sense as a pair for background work. If a persona sets model but does not set provider, foreground runs use the agent-runner default provider, and background runs use backgroundAgent.defaultProvider. Talon no longer forwards a persona model across providers in that case.

Use this pattern when you want the same provider/model pairing in both foreground and background contexts:

personas:
- name: coder
provider: codex-cli
model: gpt-5.4

If you leave out provider, background tasks fall back to the background default provider and use that provider’s normal model selection instead.

Validate that a provider is installed, authenticated, and working:

Terminal window
npx talonctl test-provider --name claude-code
npx talonctl test-provider --name codex-cli
npx talonctl test-provider --name gemini-cli
FlagDescription
--name <name>Provider name to validate

The command runs an isolated smoke test and reports authentication status, version, and a sample generation.

All four providers support context rotation when a session grows too large. Configure thresholds per provider under contextManagement:

FieldDescription
triggerMetricToken metric to monitor (cache_read_input_tokens works for all providers)
thresholdRatioFraction of contextWindowTokens that triggers rotation
recentMessageCountVerbatim messages to carry forward after rotation
summarizerSub-agent used to compress history before rotation

For Claude Code, cache_total_input_tokens is the strongest latency signal as it tracks the full cached session footprint. For Codex and Gemini, cache_read_input_tokens is the recommended metric. For openai-compatible, use cache_read_input_tokens only if the upstream exposes cache counts; otherwise use input_tokens.

Once a thread has run on a provider, Talon keeps using that provider for subsequent messages on the same thread. This preserves session continuity for resumable providers (Claude Code and Codex CLI), and it keeps non-resumable providers such as Gemini and openai-compatible sticky until you explicitly reset affinity.

Terminal window
npx talonctl list-threads --channel my-telegram

Shows all persisted threads for a channel with their external IDs, latest provider, latest status, and last activity.

Terminal window
# With confirmation prompt
npx talonctl reset-provider-affinity --channel my-telegram --external-id 123456789
# Skip confirmation (for automation)
npx talonctl reset-provider-affinity --channel my-telegram --external-id 123456789 --yes
# Reset every thread on one channel
npx talonctl reset-provider-affinity --channel slack-engineer --all --yes

After a reset, the next message on that thread uses normal persona/default provider selection. Run history is not modified — a reset marker is stored on the thread.

The --external-id value is connector-specific:

ConnectorExternal ID
Telegramchat_id
Slack<channelId>:<thread_ts> or <channelId>
TerminalclientId
WhatsAppsender wa_id
Email<address>:<messageId>

:::tip Mixing providers For interactive conversations, Claude Code is still the strongest default. Codex CLI is a good fit when you want streaming tool-aware coding sessions on OpenAI models. openai-compatible is the flexible option when you want to route a persona through Ollama or another compatible endpoint without changing the rest of Talon’s execution stack. :::