Skip to content

angee.agents.runtimes

Agent runtimes — the programs an agent is rendered into (claude-code, opencode).

An :class:Agent selects one of these by runtime_class (an ImplClassField keyed against ANGEE_AGENT_RUNTIME_CLASSES). The runtime owns the facts that differ between agent programs and that the inference provider does not know:

  • which operator service template renders it (service_template_name),
  • how it consumes an inference credential as container env (:meth:auth_env) — the same Anthropic OAuth token feeds claude-code's CLAUDE_CODE_OAUTH_TOKEN but opencode reads only ANTHROPIC_API_KEY, so the env block is a (runtime × provider × credential-kind) fact, not a provider-only one,
  • which credential kinds it can actually use (:attr:supported_credential_kinds), so the provision flow refuses an unworkable pairing up front instead of rendering a service that silently falls back,
  • the secret payload synced to the operator (:meth:auth_secret_value) — most runtimes sync the raw token, but OpenCode's OAuth path syncs a base64 auth.json,
  • the model handle in its own convention (:meth:model_handle).

The inference backend stays the owner of vendor-native primitives (the credential value and the vendor SDK's own api_key_env); a runtime composes those.

operator_secret_ref

python
def operator_secret_ref(secret_name: str) -> str

Return the operator placeholder that resolves to a stored secret in the container.

The single home of the ${secret.<name>} operator-secret contract that both the inference auth env and the per-MCP-server bearer env reference; the operator substitutes the value at compose-render, so it never transits the browser.

AgentRuntime

python
class AgentRuntime(ImplBase)

Base agent runtime: the generic, API-key-only program (e.g. opencode).

Reads the provider's own api_key_env and renders the catalogue model handle verbatim. Subclasses override for runtime-specific auth shapes (claude-code's OAuth env) or handle conventions.

renders_service

python
@property
def renders_service() -> bool

Whether this runtime renders an operator service (vs workspace-only).

supports_credential

python
def supports_credential(credential: Any) -> bool

Whether this runtime can authenticate inference with credential.

Takes the whole credential (not just its kind) so a runtime can refuse a credential whose shape it can't use — e.g. an OAuth token with no refresh token — up front, not only an unsupported kind.

model_handle

python
def model_handle(model: Any) -> str

Return the selected model handle in this runtime's convention.

The generic runtime renders the catalogue handle verbatim (e.g. opencode's anthropic/claude-… provider-qualified handle).

auth_env

python
def auth_env(*, backend: InferenceBackend, credential: Any,
             secret_name: str) -> dict[str, str]

Return the container env block this runtime uses to authenticate inference.

Secret-bearing vars carry the operator ${secret.<name>} placeholder; the value is synced server-side. An unsupported credential kind fails here, at the runtime owner, before a service is rendered.

auth_secret_value

python
def auth_secret_value(credential: Any) -> str

Return the secret payload synced to the operator store for credential.

The value stored under the agent's inference secret name and that :meth:auth_env's ${secret.<name>} placeholder resolves to in the container. The generic runtime syncs the raw credential secret (API key or bearer token); a runtime needing a richer shape (OpenCode's OAuth auth.json) overrides this.

NoRuntime

python
class NoRuntime(AgentRuntime)

Null-object runtime for a workspace-only agent — renders no service.

OpenCodeRuntime

python
class OpenCodeRuntime(AgentRuntime)

OpenCode (ACP over a WebSocket): an API key, or Anthropic Personal-Plans OAuth.

A static key renders the provider's own key env (ANTHROPIC_API_KEY etc.). OpenCode has no env path for an OAuth token — it reads OAuth only from its native auth.json store and needs a community Anthropic auth plugin (bundled in the opencode service image) to refresh and bear the token. We sync that store as a base64 blob in :attr:oauth_env; the image entrypoint decodes it into OPENCODE_AUTH_CONTENT. base64 keeps the JSON (quotes, braces) opaque to YAML and the operator's secret substitution. The model handle is the catalogue's provider-qualified id (e.g. anthropic/claude-opus-4-8).

WARNING: using a Claude Pro/Max (Personal Plans) OAuth token in OpenCode is against Anthropic's terms and risks account suspension — OpenCode removed built-in support in 1.3.0. Prefer a static API-key credential. OAuth stays disabled until the operator sets :attr:oauth_enabled_setting and builds the opencode image with the auth plugin (see OPENCODE_ANTHROPIC_AUTH_PLUGIN in the service Dockerfile); enabling it without the plugin would silently drop Anthropic from the model list.

supports_credential

python
def supports_credential(credential: Any) -> bool

Allow OAuth only when opted in (plugin bundled) and the token can be refreshed.

OpenCode's plugin renews the access token from the stored refresh token, so an OAuth credential carrying no refresh token would authenticate only until the short-lived access token expires — refuse it up front rather than provision an agent that dies silently. Static keys defer to the base (which OpenCode always supports).

auth_env

python
def auth_env(*, backend: InferenceBackend, credential: Any,
             secret_name: str) -> dict[str, str]

Render the OAuth auth.json env (base64), or the provider's static key env.

auth_secret_value

python
def auth_secret_value(credential: Any) -> str

Sync OpenCode's base64 auth.json for OAuth, else the raw key (static).

ClaudeCodeRuntime

python
class ClaudeCodeRuntime(AgentRuntime)

Claude Code: Anthropic-native, accepts both a static key and an OAuth token.

An OAuth credential renders Claude Code's token env plus the Anthropic beta header; a static key renders the vendor ANTHROPIC_API_KEY. The handle is the provider's native model name (Claude Code talks to Anthropic directly).

model_handle

python
def model_handle(model: Any) -> str

Return the provider's native model name, falling back to the catalogue handle.

auth_env

python
def auth_env(*, backend: InferenceBackend, credential: Any,
             secret_name: str) -> dict[str, str]

Render Claude Code's OAuth token env (plus beta header), or the static key env.

Released under the AGPL-3.0 License.