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.
Supported providers
Section titled “Supported providers”Four providers ship out of the box:
| Provider | Strategy | Session resumption | Context window | Prerequisites |
|---|---|---|---|---|
claude-code | SDK + CLI | Yes | 200k tokens | Claude Code CLI, authenticated |
gemini-cli | CLI | No | 1M tokens | Gemini CLI, authenticated |
codex-cli | CLI | Yes | 400k tokens | Codex CLI (codex auth) |
openai-compatible | Wrapper CLI | No | Configurable | Any 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.
Configuration
Section titled “Configuration”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| Field | Description |
|---|---|
defaultProvider | Provider used when no per-persona override is set |
providers.<name>.enabled | Enable or disable this provider |
providers.<name>.command | Runtime command to invoke (claude, gemini, codex, or node for openai-compatible) |
providers.<name>.contextWindowTokens | Context window size for rotation calculations |
providers.<name>.options | Provider-specific options (for example defaultModel for codex-cli, or baseUrl / providerId for openai-compatible) |
OpenAI-compatible provider
Section titled “OpenAI-compatible provider”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: nodeis expected. Talon launches its bundled wrapper under Node for this provider.options.baseUrlpoints at the OpenAI-compatible endpoint, usually ending in/v1.options.defaultModelis the model Talon should request if the persona does not overridemodel.options.providerIdtells Talon whichauth.providers.<name>slot to read first.- If
auth.providers.<options.providerId>is absent, Talon falls back toauth.providers.openai-compatible.
Prompt caching metrics
Section titled “Prompt caching metrics”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_tokensonly when the upstream actually reports cached token counts - use
triggerMetric: input_tokensfor Ollama or any compatible server that does not
Background workers with openai-compatible
Section titled “Background workers with openai-compatible”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.
Tool output excerpting
Section titled “Tool output excerpting”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 TALONmarker. The marker includes thetoolCallIdand 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.
| Option | Default | Description |
|---|---|---|
toolOutputCap | 4000 | Maximum 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.
:::
Per-persona provider override
Section titled “Per-persona provider override”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 personaA2A delegation always runs the target persona on its own configured provider, regardless of which provider the source thread is using.
Background-agent model selection
Section titled “Background-agent model selection”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.4If you leave out provider, background tasks fall back to the background default provider and use that provider’s normal model selection instead.
Testing a provider
Section titled “Testing a provider”Validate that a provider is installed, authenticated, and working:
npx talonctl test-provider --name claude-codenpx talonctl test-provider --name codex-clinpx talonctl test-provider --name gemini-cli| Flag | Description |
|---|---|
--name <name> | Provider name to validate |
The command runs an isolated smoke test and reports authentication status, version, and a sample generation.
Context management
Section titled “Context management”All four providers support context rotation when a session grows too large. Configure thresholds per provider under contextManagement:
| Field | Description |
|---|---|
triggerMetric | Token metric to monitor (cache_read_input_tokens works for all providers) |
thresholdRatio | Fraction of contextWindowTokens that triggers rotation |
recentMessageCount | Verbatim messages to carry forward after rotation |
summarizer | Sub-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.
Thread and provider affinity
Section titled “Thread and provider affinity”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.
Inspecting affinity
Section titled “Inspecting affinity”npx talonctl list-threads --channel my-telegramShows all persisted threads for a channel with their external IDs, latest provider, latest status, and last activity.
Resetting affinity
Section titled “Resetting affinity”# With confirmation promptnpx 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 channelnpx talonctl reset-provider-affinity --channel slack-engineer --all --yesAfter 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:
| Connector | External ID |
|---|---|
| Telegram | chat_id |
| Slack | <channelId>:<thread_ts> or <channelId> |
| Terminal | clientId |
sender wa_id | |
<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.
:::