Skip to content

Three Providers, One Daemon: Codex CLI, Provider Affinity, and Smarter A2A

Three PRs landed this week that fundamentally change how Talon handles agent execution. You can now run Claude Code, Gemini CLI, and Codex CLI in the same daemon — routing different personas to different providers — while a new set of tools gives you full control over thread affinity and A2A task status.

OpenAI’s Codex CLI joins claude-code and gemini-cli as a supported execution provider (PR #147). Configure it under agentRunner.providers and backgroundAgent.providers just like the other two:

agentRunner:
defaultProvider: claude-code
providers:
codex-cli:
enabled: true
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

Foreground Codex threads are resumable — the session persists across messages on the same thread, the same way Claude Code sessions do. Background Codex runs are ephemeral. The context window is 400k tokens.

To validate your install before enabling it in production, use the updated test-provider command:

Terminal window
npx talonctl test-provider --name codex-cli

With three providers available, you can now give different personas different execution backends. A coordinator persona running on Claude Code can delegate coding tasks to a codex-cli persona and document analysis to a gemini-cli persona — all in the same daemon, no external orchestration needed.

Thread affinity: sticky by design, resettable on demand

Section titled “Thread affinity: sticky by design, resettable on demand”

Talon has always kept threads sticky to their last-used provider to preserve session continuity for resumable providers. PR #152 surfaces that behavior explicitly and gives you tools to manage it.

The new list-threads command shows every persisted thread for a channel along with its current provider affinity, status, and last activity:

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

When you want to move a thread to a different provider — say, you’ve reconfigured a persona or want to test a new model — use reset-provider-affinity:

Terminal window
npx talonctl reset-provider-affinity --channel my-telegram --external-id 123456789

This stores a reset marker on the thread without touching run history. The next message picks up the normal persona/default provider selection. Add --yes to skip the confirmation prompt in scripts.

A2A provider isolation and persona_task_status

Section titled “A2A provider isolation and persona_task_status”

PR #153 fixes a subtle footgun in A2A delegation: previously, a delegated task could inherit the source thread’s provider affinity rather than using the target persona’s configured provider. That’s now fixed — delegated tasks always run on the target persona’s own provider, full stop.

The other big addition is persona_task_status. When persona_send with await_reply: true times out before the target persona finishes (the default wait is now 5 minutes, configurable with timeout_ms), the tool returns a structured response containing the task_id. You can then poll the result at your own pace:

persona_task_status({
task_id: "abc123",
wait_ms: 60000
})

The wait_ms parameter lets you poll until the task reaches a terminal state or the duration elapses — no busy loops required. All three persona tools (persona_send, persona_task_status, and persona_list) require only the single persona.send:* capability grant.

The pattern that emerges from these three PRs is clean: define personas with explicit providers, let Claude Code handle interactive conversations, route batch work to Codex or Gemini, and use persona_task_status to bridge long-running A2A tasks without blocking. Affinity is managed automatically; when you need to override it, the CLI tools are right there.

Full configuration details are in the new Providers guide. For A2A patterns including persona_task_status, see the A2A Protocol guide.