Skip to content

runtime

strands_teams.runtime

Vendor-free specialist-runtime contracts (ASTR §10, §2.1).

This module defines the typed boundary between the strands_teams framework and any autonomous external coding harness (Phase 3 / spec 004-coding-runtime). It is deliberately domain- and vendor-free: it imports no coding-agent SDK (claude_agent_sdk, codex, openai_codex) and no subprocess. The concrete adapters that DO import those SDKs live in the separate strands_teams_runtimes workspace package; core only owns the contract they satisfy (plan §3; research-coding-runtimes.yaml architecture).

The contract has three parts:

  • :class:ResourceUsage — a FrozenModel carrying the cost/token/turn/duration accounting a harness reports.
  • :class:SpecialistResult — a FrozenModel carrying only the structured outcome of a harness run: a disposition, the worktree-relative paths it changed, typed :class:~strands_teams.models.Finding objects (reusing the P1 type), evidence refs (reusing the P1 :class:~strands_teams.models.Evidence type), a residual-risk note, and resource usage. It carries no raw transcript, private chain-of-thought, or full terminal command log — that is an ASTR §10.4 invariant and a context-budget necessity.
  • :class:SpecialistRuntime — a Protocol (structural interface) declaring submit / status / send_input / cancel / collect. collect returns a :class:SpecialistResult, never the transcript.

SpecialistDisposition module-attribute

SpecialistDisposition = Literal[
    "completed", "partial", "failed", "refused"
]

How a specialist harness run concluded.

  • completed — the harness finished its task successfully.
  • partial — the harness ran to a limit (e.g. max turns) with usable but incomplete work.
  • failed — the harness errored, timed out, or exceeded its budget without a usable result.
  • refused — the harness declined the task (e.g. a safety refusal).

ResourceUsage

Bases: FrozenModel

Cost and token accounting reported by a specialist harness run (ASTR §10.4).

Immutable and extra="forbid" (inherited from :class:FrozenModel). Every field defaults to a zero-ish value so an adapter can report a partial accounting (e.g. a Codex run that surfaces token counts but no dollar cost) without constructing an invalid object.

Attributes:

Name Type Description
cost_usd float

Dollar cost of the run (Claude ResultMessage.total_cost_usd; 0.0 when the provider reports none).

input_tokens int

Total input tokens consumed.

output_tokens int

Total output tokens generated.

num_turns int

Number of agent turns (tool-use round trips) the harness took.

duration_seconds float

Wall-clock duration of the run, in seconds.

SpecialistResult

Bases: FrozenModel

The structured outcome of one specialist harness run (ASTR §10.4).

This is the ONLY thing that crosses the harness boundary back into the swarm's context. It carries a disposition, the artifacts the harness changed, typed findings, evidence refs, a residual-risk note, and resource usage — but never the raw transcript, private chain-of-thought, or full terminal command log (ASTR §10.4; plan §5 "Boundary discipline"). Immutable and extra="forbid" (inherited from :class:FrozenModel), so an out-of-range disposition or an unexpected extra field is rejected at construction rather than silently coerced (AC-2-7).

Attributes:

Name Type Description
disposition SpecialistDisposition

How the run concluded — one of completed / partial / failed / refused.

artifacts list[str]

Worktree-relative path strings the harness created or modified (ground truth derivable from git status --porcelain). Typed as plain strings in Phase 3; a later phase MAY enrich these to ArtifactRevision objects (spec cross-phase note; P4 not present here).

findings list[Finding]

Typed :class:~strands_teams.models.Finding objects the harness produced (reuses the P1 type — never redefined here).

evidence list[Evidence]

Standalone :class:~strands_teams.models.Evidence refs backing the result (reuses the P1 evidence-reference type).

residual_risk str

A short prose note on risk the harness could not eliminate (empty string when none).

resource_usage ResourceUsage

Cost/token/turn/duration accounting for the run.

SpecialistRuntime

Bases: Protocol

Structural interface for an autonomous external coding harness (ASTR §10).

A SpecialistRuntime drives one bounded coding task in its own OS subprocess (a Claude Agent SDK query() subprocess, or codex exec) and reports back only a :class:SpecialistResult. This Protocol is defined in strands_teams core without importing any coding-agent SDK or subprocess — the concrete adapters live in strands_teams_runtimes and are injected into the coding tool by dependency injection, so core stays vendor-free (plan §3; research-coding-runtimes.yaml architecture).

Implementations are typically async because they await a subprocess; a runtime_checkable Protocol only checks method presence, not signatures, so both sync and async adapters satisfy it structurally.

The five methods model a submit/poll/collect lifecycle:

  • submit(task, *, workspace, model_id, capabilities) — start a harness run rooted at workspace (its only writable root) and return an opaque run-handle/id.
  • status(handle) — report the run's current lifecycle state.
  • send_input(handle, text) — feed additional input to a running harness.
  • cancel(handle) — cancel a running harness (e.g. on a wall-clock timeout).
  • collect(handle) — return the :class:SpecialistResult. Returns the structured result only — never the harness raw transcript, private chain-of-thought, or full terminal command log (ASTR §10.4).

submit

submit(task, *, workspace, model_id, capabilities=...)

Start a harness run rooted at workspace; return an opaque run handle.

Source code in packages/strands-teams/src/strands_teams/runtime.py
def submit(
    self,
    task: str,
    *,
    workspace: object,
    model_id: str,
    capabilities: Mapping[str, object] | None = ...,
) -> object:
    """Start a harness run rooted at ``workspace``; return an opaque run handle."""
    ...

status

status(handle)

Report the run's current lifecycle state (e.g. running / done).

Source code in packages/strands-teams/src/strands_teams/runtime.py
def status(self, handle: object) -> str:
    """Report the run's current lifecycle state (e.g. ``running`` / ``done``)."""
    ...

send_input

send_input(handle, text)

Feed additional input to a running harness.

Source code in packages/strands-teams/src/strands_teams/runtime.py
def send_input(self, handle: object, text: str) -> None:
    """Feed additional input to a running harness."""
    ...

cancel

cancel(handle)

Cancel a running harness (e.g. on a wall-clock timeout).

Source code in packages/strands-teams/src/strands_teams/runtime.py
def cancel(self, handle: object) -> None:
    """Cancel a running harness (e.g. on a wall-clock timeout)."""
    ...

collect

collect(handle)

Return the structured :class:SpecialistResult — never the raw transcript (ASTR §10.4).

Source code in packages/strands-teams/src/strands_teams/runtime.py
def collect(self, handle: object) -> SpecialistResult:
    """Return the structured :class:`SpecialistResult` — never the raw transcript (ASTR §10.4)."""
    ...