Schema
schema
¶
Pydantic v2 schema for agent-roster YAML files.
Each resources/agents/*.yaml (and any user override under
~/.config/terok/agent/agents/*.yaml) is parsed into RawAgentYaml;
each resources/providers/*.yaml into RawProvider.
These project onto the runtime dataclasses
(Agent,
Provider,
AuthProvider, …).
Validation guarantees:
- Strict keys: every section uses
extra="forbid", so a typo (headles:,oauth_refesh:) fails fast with a precise error instead of silently falling back to defaults. - Type-checked values:
modesonly acceptsoauth/api_key,credential_typeonly accepts the four known kinds,help.sectiononly acceptsagent/dev_tool. - Required fields:
provider.upstream,provider.auth(≥1 mode),auth.host_dir,auth.container_mountraise on missing. - Coercions:
install.depends_onaccepts a single string or a list.
Each Raw… model exposes a to_dataclass(...) method that produces
the corresponding frozen runtime object. The roster loader threads
context (the agent's name and label) through these methods rather than
encoding it in the schema itself — keeps the schema purely declarative
and matches the per-file YAML shape.
HELP_SECTIONS = get_args(HelpSection)
module-attribute
¶
All valid HelpSection values, as a tuple (single source of truth).
StrOrStrList = Annotated[list[str], BeforeValidator(_coerce_str_to_list)]
module-attribute
¶
Permits foo: bar as a shorthand for foo: [bar].
PostCaptureState = Annotated[dict[str, dict], BeforeValidator(_coerce_none_to_empty_dict)]
module-attribute
¶
Mapping of filename → JSON patch. post_capture_state: ~ collapses to {}.
AgentKind = Literal['native', 'harness', 'frontend', 'tool', 'infra']
module-attribute
¶
Kind of roster entry, chosen to predict behaviour:
native— a CLI with a fixed protocol + default provider (claude, codex, vibe, copilot)harness— a multi-provider driver, provider supplied at runtime (opencode, pi)frontend— drives co-installed agents in-container (toad)tool— a non-LLM API client (gh, glab, sonar, coderabbit)infra— a support service, not user-invoked (caddy)
__all__ = ['HELP_SECTIONS', 'AgentKind', 'RawAgentYaml', 'RawAuth', 'RawAuthKey', 'RawAutoApprove', 'RawCapabilities', 'RawGitIdentity', 'RawHeadless', 'RawHelp', 'RawInstall', 'RawMountSpec', 'RawOAuthRefresh', 'RawLauncher', 'RawOpenCode', 'RawProvider', 'RawProviderAuth', 'RawProviderAuthMode', 'RawProviderBinding', 'RawSession', 'RawSidecar', 'RawWrapper', 'VaultRouteEntry']
module-attribute
¶
StrictModel
¶
RawGitIdentity
¶
Bases: StrictModel
git_identity: — author/committer override per agent.
RawHeadless
¶
Bases: StrictModel
headless: — flags and subcommand for non-interactive prompt invocation.
subcommand = Field(default=None, description='Subcommand for headless mode (e.g. ``exec`` for codex)')
class-attribute
instance-attribute
¶
prompt_flag = Field(default='-p', description='Flag for the prompt; ``""`` for positional')
class-attribute
instance-attribute
¶
model_flag = Field(default=None, description='Flag for model override')
class-attribute
instance-attribute
¶
max_turns_flag = Field(default=None, description='Flag for maximum turns')
class-attribute
instance-attribute
¶
verbose_flag = Field(default=None, description='Flag for verbose output')
class-attribute
instance-attribute
¶
output_format_flags = Field(default_factory=list, description='Flags for structured output')
class-attribute
instance-attribute
¶
RawAutoApprove
¶
Bases: StrictModel
auto_approve: — env vars and flags injected when TEROK_UNRESTRICTED=1.
RawSession
¶
Bases: StrictModel
session: — session resume / continue capability flags.
RawCapabilities
¶
Bases: StrictModel
capabilities: — agent-specific feature toggles.
RawLauncher
¶
Bases: StrictModel
wrapper.launcher: — the per-task launcher script and when it runs.
RawWrapper
¶
Bases: StrictModel
wrapper: — in-container shell-wrapper behavior.
RawOpenCode
¶
Bases: StrictModel
opencode: — OpenAI-compatible provider config for OpenCode-based agents.
display_name
instance-attribute
¶
base_url
instance-attribute
¶
preferred_model
instance-attribute
¶
fallback_model
instance-attribute
¶
env_var_prefix
instance-attribute
¶
config_dir
instance-attribute
¶
auth_key_url
instance-attribute
¶
api_key_hint = Field(default=None, description="Override for the auto-derived auth provider's API-key hint")
class-attribute
instance-attribute
¶
to_dataclass()
¶
Project to the runtime OpenCodeProviderConfig.
Source code in src/terok_executor/roster/schema.py
RawAuthKey
¶
Bases: StrictModel
auth.auth_key: — printf-template-driven API-key prompt for tools.
RawAuth
¶
Bases: StrictModel
auth: — credential-capture behavior (OAuth container or API-key prompt).
host_dir = Field(description='Single-segment dir under mounts_dir() (e.g. ``_codex-config``)')
class-attribute
instance-attribute
¶
container_mount = Field(description='Mount point inside the container')
class-attribute
instance-attribute
¶
command = Field(default=None, description='Container command for OAuth mode; derived from auth_key when absent')
class-attribute
instance-attribute
¶
auth_key = None
class-attribute
instance-attribute
¶
banner_hint = ''
class-attribute
instance-attribute
¶
extra_run_args = Field(default_factory=list)
class-attribute
instance-attribute
¶
modes = Field(default_factory=(lambda: ['api_key']))
class-attribute
instance-attribute
¶
device_auth = Field(default=False, description='OAuth flow has a headless device-code variant, offered in the auth prompt')
class-attribute
instance-attribute
¶
api_key_hint = ''
class-attribute
instance-attribute
¶
post_capture_state = Field(default_factory=dict, description='JSON state files to merge into the auth mount post-capture')
class-attribute
instance-attribute
¶
to_dataclass(*, name, label)
¶
Project to the runtime AuthProvider.
name and label come from the parent file (the YAML doesn't repeat
them inside auth:).
Source code in src/terok_executor/roster/schema.py
RawOAuthRefresh
¶
Bases: StrictModel
vault.oauth_refresh: — token-refresh endpoint and client config.
RawSidecar
¶
Bases: StrictModel
sidecar: — separate L1 image + env-mapped credentials for tool runners.
tool_name = None
class-attribute
instance-attribute
¶
env_map = Field(default_factory=dict)
class-attribute
instance-attribute
¶
to_dataclass(*, default_name)
¶
Project to a runtime SidecarSpec.
Source code in src/terok_executor/roster/schema.py
RawInstall
¶
Bases: StrictModel
install: — Dockerfile fragments emitted into the L1 image.
depends_on = Field(default_factory=list)
class-attribute
instance-attribute
¶
run_as_root = ''
class-attribute
instance-attribute
¶
run_as_dev = ''
class-attribute
instance-attribute
¶
to_dataclass()
¶
Project to a runtime InstallSpec.
Source code in src/terok_executor/roster/schema.py
RawHelp
¶
Bases: StrictModel
help: — one-line entry shown in the in-container help banner.
RawMountSpec
¶
Bases: StrictModel
One entry in the mounts: list — explicit shared-config mount.
VaultRouteEntry
¶
Bases: StrictModel
One entry in the generated routes.json consumed by the sandbox vault.
The on-disk file is a top-level {provider_name: VaultRouteEntry} dict.
Empty optional fields (path_upstreams, oauth_extra_headers,
oauth_refresh) are dropped from the serialized output via
exclude_none, keeping the produced file small and diff-friendly.
upstream = Field(description='Upstream API base URL')
class-attribute
instance-attribute
¶
auth_header = Field(description='HTTP header name for the real credential')
class-attribute
instance-attribute
¶
auth_prefix = Field(description='Prefix prepended to the token (e.g. ``"Bearer "``)')
class-attribute
instance-attribute
¶
path_upstreams = Field(default=None, description='Path-prefix → upstream-base overrides')
class-attribute
instance-attribute
¶
oauth_extra_headers = Field(default=None, description='Headers added when forwarding OAuth credentials')
class-attribute
instance-attribute
¶
oauth_refresh = Field(default=None, description='Token-refresh endpoint config (``token_url``, ``client_id``, optional ``scope``)')
class-attribute
instance-attribute
¶
RawProviderAuthMode
¶
Bases: StrictModel
One auth.api_key / auth.oauth sub-block — the wire attachment for a mode.
header = Field(description='HTTP header carrying the credential (e.g. ``Authorization``)')
class-attribute
instance-attribute
¶
prefix = Field(default='', description='Token prefix (e.g. ``"Bearer "``)')
class-attribute
instance-attribute
¶
extra_headers = Field(default_factory=dict, description='Headers added only for this mode')
class-attribute
instance-attribute
¶
to_dataclass()
¶
Project to a runtime ProviderAuth.
RawProviderAuth
¶
Bases: StrictModel
auth: — at least one of api_key / oauth must be present.
Declaring both with different headers is how a provider expresses the
OAuth-or-API-key header switch (Anthropic); the projection collapses that
to the auth_header: dynamic wire sentinel
(see Provider.wire_auth).
RawProvider
¶
Bases: StrictModel
Full schema for one resources/providers/*.yaml file.
The file's stem (anthropic.yaml → "anthropic") supplies the provider
name; the YAML never repeats it. Strict keys reject typos
(upstreams:, oath:) the same way the agent schema does.
upstream = Field(description='Upstream API base URL')
class-attribute
instance-attribute
¶
auth
instance-attribute
¶
path_upstreams = Field(default_factory=dict)
class-attribute
instance-attribute
¶
oauth_refresh = None
class-attribute
instance-attribute
¶
shared_domain = False
class-attribute
instance-attribute
¶
serves = Field(default_factory=dict, description='Wire protocol → container-facing base path (LLM providers only)')
class-attribute
instance-attribute
¶
opencode = Field(default=None, description='OpenCode wrapper config for a harness-driven provider (Blablador, …)')
class-attribute
instance-attribute
¶
install = Field(default=None, description='Pinned-alias install fragment for a harness-driven provider')
class-attribute
instance-attribute
¶
help = Field(default=None, description='Help-listing entry for the command')
class-attribute
instance-attribute
¶
to_dataclass(*, name)
¶
Project to a runtime Provider.
Source code in src/terok_executor/roster/schema.py
RawProviderBinding
¶
Bases: StrictModel
provider: — how an agent routes to (delivers) a provider.
The delivery concern lifted out of the agent vault: block: which
provider this agent uses (default) plus the per-agent env-var /
config-patch plumbing. The endpoint concern (upstream, wire auth) lives
in the named RawProvider.
default = Field(default=None, description='Provider name this agent routes to (None for harnesses)')
class-attribute
instance-attribute
¶
token_env = Field(default_factory=dict)
class-attribute
instance-attribute
¶
base_url_env = ''
class-attribute
instance-attribute
¶
socket_env = ''
class-attribute
instance-attribute
¶
credential_file = ''
class-attribute
instance-attribute
¶
credential_file_writable = Field(default=False, description="Mount the credential file writable instead of under a read-only shadow. Set when the tool stores credentials and settings in the same file it must rewrite on startup (e.g. glab's config.yml) — the shadow would block the write, and the file persists in the shared mount instead of being contained.")
class-attribute
instance-attribute
¶
credential_type = 'api_key'
class-attribute
instance-attribute
¶
config_patch = None
class-attribute
instance-attribute
¶
to_dataclass()
¶
Project to a runtime ProviderBinding.
Source code in src/terok_executor/roster/schema.py
RawAgentYaml
¶
Bases: StrictModel
Full schema for one agent YAML file.
The file's stem (e.g. claude.yaml → "claude") supplies the
roster name; the YAML never repeats it inside. roster_version
is stripped before validation by the loader's compat check, so it
is intentionally absent here.
kind = 'native'
class-attribute
instance-attribute
¶
label = Field(default=None, description='Human-readable display name')
class-attribute
instance-attribute
¶
binary = Field(default=None, description='CLI binary name (defaults to roster name)')
class-attribute
instance-attribute
¶
git_identity = None
class-attribute
instance-attribute
¶
headless = None
class-attribute
instance-attribute
¶
auto_approve = None
class-attribute
instance-attribute
¶
session = None
class-attribute
instance-attribute
¶
capabilities = None
class-attribute
instance-attribute
¶
wrapper = None
class-attribute
instance-attribute
¶
auth = None
class-attribute
instance-attribute
¶
protocol = Field(default=None, description='Wire protocol the agent speaks (anthropic-messages / openai-chat / …)')
class-attribute
instance-attribute
¶
provider = None
class-attribute
instance-attribute
¶
sidecar = None
class-attribute
instance-attribute
¶
install = None
class-attribute
instance-attribute
¶
help = None
class-attribute
instance-attribute
¶
mounts = Field(default_factory=list)
class-attribute
instance-attribute
¶
web_ingress = Field(default=False, description='Whether this entry publishes a host HTTP port')
class-attribute
instance-attribute
¶
resolve_label(name)
¶
to_agent(name)
¶
Project to a runtime Agent.