Skip to main content

Module agent_context

Module agent_context 

Source
Expand description

AgentContextMiddleware — the innermost SpawnerLayer that materializes AgentContextView once per spawn (Contract C, GH #20), now also the receptacle that resolves and merges the BP-declared agent-context supply tiers (GH #21 Phase 1).

Layered FIRST (innermost, i.e. added earliest in service::task_launch::TaskLaunchService::launch, before the alias / worker-binding blocks) so it observes the ctx.meta.runtime keys the outer TaskInputMiddleware / ProjectNameAliasMiddleware / WorkerBindingMiddleware layers insert. See the module doc on crate::core::agent_context for the full Contract C narrative and the two-axis fan-out diagram.

Unlike TaskInputMiddleware / ProjectNameAliasMiddleware (which only mutate ctx), this layer ALSO snapshots the view (paired with the resolved policy, GH #23) into EngineState.agent_ctx, keyed (task_id, attempt) — the Worker axis (Engine::fetch_worker_payload{,_trusted}) reads the view half back from there, mirroring how EngineState.prompts / .systems are populated and later fetched.

§GH #21 Phase 1: the supply tiers this layer merges

service::task_launch::derive_agent_ctx / derive_context_policies resolve four pieces out of the launched Blueprintdefault_agent_ctx / per-agent AgentMeta.ctx (the context tiers) and default_context_policy / per-agent AgentMeta.context_policy (the policy tiers) — and hand them to AgentContextMiddleware::new. On every spawn:

  1. The context tiers are shallow-merged (agent wins on key collision; a tier whose declared value isn’t a JSON Object is warned and skipped, never failing the spawn).
  2. Every merged key is inserted into ctx.meta.runtime only-if-absent — an outer, runtime-supplied value (e.g. TaskInputMiddleware’s work_dir) always outranks this BP-declared default, with no priority code beyond insertion order (SpawnerStack outer-to-inner = later tier wins the race to insert first).
  3. AgentContextView::from_ctx then reads the (possibly BP-defaulted) ctx.meta.runtime back out, so known-key defaults (project_root / work_dir / …) flow into the view automatically; merged keys that aren’t one of those named fields are folded into view.extra instead (also only-if-absent).
  4. The policy tiers resolve to a single effective ContextPolicy (per-agent outranks BP-global; pass-all when neither is declared) and are applied via AgentContextView::apply_policy.

§GH #21 Phase 2: the Step tier

Before the Agent/BP-global merge above, this layer also reads ctx.meta.runtime[STEP_CTX_KEY] — the Step tier’s resolved bundle, threaded through by Engine::dispatch_attempt_with from TaskSpec.step_ctx (itself resolved by EngineDispatcher::dispatch’s $step_meta envelope handling in crate::blueprint). When it is a JSON Object, its keys are applied with the SAME only-if-absent + extra-fold mechanics as the Agent/BP-global tiers, but ORDERED FIRST — so a Step-declared key wins over an Agent/BP-global-declared key for the same name (Run/Task tier keys are already individually present in ctx.meta.runtime by the time this layer runs and are therefore untouched either way — the full cascade is Run > Task > Step > Agent > BP-global). A non-Object STEP_CTX_KEY value is warned and skipped, same as a malformed Agent/BP-global tier. The raw STEP_CTX_KEY bundle itself stays in the runtime bag verbatim (in-process workers may read it directly) — it is NOT folded into view.extra as a whole; only its individual keys are.

Structs§

AgentContextMiddleware
SpawnerLayer that materializes an AgentContextView from ctx (after merging in the BP-declared agent-context supply tiers — see the module doc), snapshots it into engine state (Worker axis source), and stashes the serialized view into ctx.meta.runtime[AGENT_CONTEXT_KEY] (Spawner axis source) before delegating to inner.