Providers
providers
¶
Agent registry + per-agent behaviour.
Each supported AI coding agent is described by an
Agent
dataclass that owns both its capability shape (flags, environment,
session handling) and the behaviour bound to that shape — config
resolution (Agent.apply_config)
and headless-command assembly (Agent.build_headless_command).
The AGENTS dict maps short names to descriptors and is
populated at package load time from the YAML roster.
LAUNCHER_ON_PROVIDER_SELECT = 'on_provider_select'
module-attribute
¶
Launcher mode: run only when a provider override is selected (default = bare binary).
LAUNCHER_ALWAYS = 'always'
module-attribute
¶
Launcher mode: run on every invocation (the launcher does per-run prep).
AGENTS = {}
module-attribute
¶
All agents, keyed by name. Loaded from resources/agents/*.yaml.
AGENT_NAMES = ()
module-attribute
¶
OPENCODE_PROVIDERS = {}
module-attribute
¶
OpenCode-driven provider name → config-dir, for the curated harness providers (Blablador, KISSKI, OpenRouter). Populated from the roster's providers at load time so this layer can drive per-provider config injection without importing the roster (which would cycle).
AgentRunConfig(model, max_turns, timeout, prompt_extra, warnings)
dataclass
¶
Resolved per-run config for a headless provider.
Produced by Agent.apply_config
after best-effort feature mapping.
model
instance-attribute
¶
Model override for providers that support it, else None.
max_turns
instance-attribute
¶
Max turns for providers that support it, else None.
timeout
instance-attribute
¶
Effective timeout in seconds.
prompt_extra
instance-attribute
¶
Extra text to append to the prompt (best-effort feature analogues).
warnings
instance-attribute
¶
Warnings about unsupported features (for user display).
CLIOverrides(model=None, max_turns=None, timeout=None, instructions=None)
dataclass
¶
CLI flag overrides for a headless agent run.
model = None
class-attribute
instance-attribute
¶
Explicit --model from CLI (takes precedence over config).
max_turns = None
class-attribute
instance-attribute
¶
Explicit --max-turns from CLI.
timeout = None
class-attribute
instance-attribute
¶
Explicit --timeout from CLI.
instructions = None
class-attribute
instance-attribute
¶
Resolved instructions text. Delivery is provider-aware.
ProviderBinding(default=None, token_env=dict(), base_url_env='', socket_env='', credential_file='', credential_type='api_key', config_patch=None)
dataclass
¶
How one agent consumes a provider — the delivery concern.
Lifted out of the agent vault: block: which provider this agent routes
to by default, and the per-agent env-var / config-patch plumbing that
carries the phantom token and vault base URL into the agent's own
configuration. The endpoint concern (upstream, wire auth) lives on the
Provider this binding names.
default = None
class-attribute
instance-attribute
¶
Provider name this agent routes to by default.
Set for agents with a fixed provider (natives → their LLM provider; tools
→ their API provider; the OpenCode-shim agents → their endpoint). None
for harnesses (opencode, pi), which take a provider at runtime.
token_env = field(default_factory=dict)
class-attribute
instance-attribute
¶
Phantom-token env var name, keyed by stored credential type.
Keys are credential types ("oauth", "pat", …); "_default" is the
fallback. Most agents read one var ({"_default": "MISTRAL_API_KEY"});
Claude swaps on OAuth ({"oauth": "CLAUDE_CODE_OAUTH_TOKEN", "_default":
"ANTHROPIC_API_KEY"}).
base_url_env = ''
class-attribute
instance-attribute
¶
Env var overridden with the vault's HTTP URL (e.g. "ANTHROPIC_BASE_URL").
socket_env = ''
class-attribute
instance-attribute
¶
Env var that receives the container-side vault socket path (HTTP-over-UNIX agents).
credential_file = ''
class-attribute
instance-attribute
¶
Credential file path relative to the auth mount (e.g. ".credentials.json").
Drives the read-only credential shadow (terok-ai/terok#873) and the doctor's leaked-secret probe.
credential_type = 'api_key'
class-attribute
instance-attribute
¶
Default credential type captured for this agent ("oauth"/"api_key"/
"oauth_token"/"pat"). The runtime token selection uses the stored
type from the vault DB; this is the authoring default.
config_patch = None
class-attribute
instance-attribute
¶
Optional shared-config patch applied after auth (e.g. Codex/Vibe config.toml).
Launcher(script, mode)
dataclass
¶
How an agent's wrapper hands off to a per-task launcher script.
A launcher script preps the agent — rewrites provider config, scopes a
picker, injects instructions — before exec-ing the binary. mode decides
when the wrapper routes through it:
LAUNCHER_ON_PROVIDER_SELECT— only when a provider override is selected; the default path runs the bare binary (a config-rewriting launcher has nothing to do without a selection).LAUNCHER_ALWAYS— every invocation (the launcher does per-run prep the bare binary can't, such as instruction injection).
Agent(name, label, binary, git_author_name, git_author_email, headless_subcommand, prompt_flag, auto_approve_env, auto_approve_flags, output_format_flags, model_flag, max_turns_flag, verbose_flag, supports_session_resume, resume_flag, continue_flag, session_file, supports_session_hook, supports_add_dir, log_format, refuse_subcommands=(), protocol=None, provider_binding=None, launcher=None)
dataclass
¶
Describes how to run one AI coding agent (all modes: interactive + headless).
name
instance-attribute
¶
Short key used in CLI dispatch (e.g. "claude", "codex").
label
instance-attribute
¶
Human-readable display name (e.g. "Claude", "Codex").
binary
instance-attribute
¶
CLI binary name (e.g. "claude", "codex", "opencode").
git_author_name
instance-attribute
¶
AI identity name for Git author/committer policy application.
git_author_email
instance-attribute
¶
AI identity email for Git author/committer policy application.
headless_subcommand
instance-attribute
¶
Subcommand for headless mode (e.g. "exec" for codex, "run" for opencode).
None means the binary uses flags only (e.g. claude -p).
prompt_flag
instance-attribute
¶
Flag for passing the prompt.
"-p" for flag-based, "" for positional (after subcommand).
auto_approve_env
instance-attribute
¶
Environment variables for fully autonomous execution.
Injected into the container env by _apply_unrestricted_env() when
TEROK_UNRESTRICTED=1. Read by agents regardless of launch path.
Claude uses /etc/claude-code/managed-settings.json instead.
auto_approve_flags
instance-attribute
¶
CLI flags injected by the shell wrapper when TEROK_UNRESTRICTED=1.
Only for agents that lack an env var or managed config mechanism
(currently Codex only). Empty for all other agents — their env vars
and /etc/ config files handle permissions across all launch paths.
output_format_flags
instance-attribute
¶
Flags for structured output (e.g. ("--output-format", "stream-json")).
model_flag
instance-attribute
¶
Flag for model override ("--model", "--agent", or None).
max_turns_flag
instance-attribute
¶
Flag for maximum turns ("--max-turns" or None).
verbose_flag
instance-attribute
¶
Flag for verbose output ("--verbose" or None).
supports_session_resume
instance-attribute
¶
Whether the agent supports resuming a previous session.
resume_flag
instance-attribute
¶
Flag to resume a session (e.g. "--resume", "--session").
continue_flag
instance-attribute
¶
Flag to continue a session (e.g. "--continue").
session_file
instance-attribute
¶
Filename in /home/dev/.terok/ for stored session ID.
Providers that capture session IDs via plugin or post-run parsing set this
to a filename (e.g. "opencode-session.txt"). Providers with their own
hook mechanism (Claude) or no session support set this to None.
supports_session_hook
instance-attribute
¶
Whether the agent supports SessionStart hooks (Claude only).
supports_add_dir
instance-attribute
¶
Whether the agent supports --add-dir "/" (Claude only).
log_format
instance-attribute
¶
Log format identifier: "claude-stream-json" or "plain".
refuse_subcommands = ()
class-attribute
instance-attribute
¶
Subcommands the in-container wrapper refuses with a friendly error.
Used to block credential-handling flows (login, logout,
setup-token) that would otherwise pollute the host-shared mount —
operators authenticate on the host via terok auth instead. Best
effort only; the firewall is the actual enforcement
(terok-ai/terok#873).
protocol = None
class-attribute
instance-attribute
¶
Wire protocol the agent speaks ("anthropic-messages" / "openai-chat" /
"openai-responses"), or None for non-LLM tools. Matched against a
provider's serves to resolve a runtime agent×provider combo.
provider_binding = None
class-attribute
instance-attribute
¶
How this agent routes to a provider — see ProviderBinding.
None for entries with no vault route of their own (harnesses, copilot).
launcher = None
class-attribute
instance-attribute
¶
Per-task launcher the wrapper hands off to — see Launcher.
None runs the bare binary (any provider override arriving via env instead,
e.g. Claude).
uses_opencode_instructions
property
¶
Whether the agent uses OpenCode's instruction system.
Only the OpenCode harness itself; the curated OpenCode-driven providers
(Blablador, KISSKI, OpenRouter) are no longer agents — they run through
the same opencode wrapper, which already carries this behaviour.
apply_config(config, overrides=None)
¶
Resolve config values for this provider with best-effort feature mapping.
CLI flag overrides take precedence over config values. When this provider lacks a feature, an analogue is used where possible (e.g. injecting max-turns guidance into the prompt), and a warning is emitted for features that have no analogue.
Source code in src/terok_executor/provider/providers.py
build_headless_command(*, timeout, model=None, max_turns=None)
¶
Assemble the bash command string for a headless agent run.
The command assumes:
init-ssh-and-repo.shhas already set up the workspace- The prompt is in
/home/dev/.terok/prompt.txt - For Claude, the
claude()wrapper function is sourced viabash -l
Returns a bash command string suitable for ["bash", "-lc", cmd].
Dispatches to provider-specific assembly: Claude routes through the
shell wrapper (which adds --add-dir, git env); everything else
uses the generic shape with subcommand + flags.
Source code in src/terok_executor/provider/providers.py
resolve_agent_value(key, config, agent_name)
¶
Extract an agent-aware config value.
Supports two forms:
- Flat value —
model: opus→ same for all agents. - Per-agent dict —
model: {claude: opus, codex: o3, _default: fast}→ looks up agent_name, falls back to_default, thenNone.
Returns None when the key is absent or has no match for the agent.
Null override behaviour: when a per-agent dict maps an agent to
null (Python None), that None is treated as "no value" and the
resolver falls back to _default. This is intentional — it allows a
lower-priority config layer to set an agent-specific value that a
higher-priority layer can effectively unset by mapping it to null,
letting the _default (or None) bubble up instead.
Internal to agent config resolution — full config-stack composition
(build_agent_config_stack, resolve_agent_config) lives in terok,
which owns the global/project/preset layer semantics.
Source code in src/terok_executor/provider/providers.py
resolve_agent(agents, name, *, default_agent=None)
¶
Look up an agent by name from agents, with fallback chain.
Resolution order: explicit name → default_agent → "claude".
Raises SystemExit if the resolved name is not found.
Source code in src/terok_executor/provider/providers.py
get_agent(name, *, default_agent=None)
¶
Resolve an agent name against the global AGENTS registry.
Convenience wrapper around resolve_agent.