import { z } from 'zod'; import { G as GuardrailContext } from './context-DKkamYX_.js'; import { a as GuardrailRuleData } from './guardrail-hooks-slK-z0Dz.js'; import { EmitInput, ExecutionEnvelope, AttrValue, CanonicalLink } from '@aaac/observability'; /** * MemoryRef — opaque typed reference for resumable agent context. * * The ref itself is a lightweight pointer; the actual memory content * is managed by the MemoryStore or held server-side by the provider. */ interface MemoryRef { /** Opaque identifier (e.g. session UUID, response ID, agent ID). */ id: string; /** Provider that generated this ref (e.g. "claude-agent-sdk", "openai-responses"). */ provider: string; /** Compatibility tag for format validation across versions. */ compat: string; /** ISO 8601 timestamp of ref creation. */ created_at: string; /** ID of the run that produced this ref, for chain tracking. */ parent_run_id?: string; } /** * Pluggable store for memory content that backs MemoryRef pointers. * * Adapters that use server-side state (OpenAI, Gemini) may not need * the store — the ref ID alone is sufficient for resume. Adapters * with local state (Claude transcript, Gemini chat history) use the * store to persist and retrieve content. */ interface MemoryStore { save(ref: MemoryRef, content: unknown): Promise; load(ref: MemoryRef): Promise; delete(ref: MemoryRef): Promise; } /** * In-memory store for testing. State is lost when the process exits. */ declare class InMemoryStore implements MemoryStore { private data; save(ref: MemoryRef, content: unknown): Promise; load(ref: MemoryRef): Promise; delete(ref: MemoryRef): Promise; } /** * observability-bridge.ts * * Bridge between @aaac/runtime execution and @aaac/observability agent-axis spans. * * Responsibilities: * - Generate ExecutionEnvelope (run_id = UUIDv7) for every task/workflow execution * - Emit agent.session (open/close) for runWorkflow() — root run span * - Emit agent.subagent (open/close) for runTask() — handoff/task span * - Emit toolchain.execution (open/close) for toolchain tool invocations * - Observer is OPTIONAL — all emit* functions are no-ops when observer is undefined * * No circular dependency: @aaac/observability does NOT import @aaac/runtime. * Types (ExecutionEnvelope, EmitInput) are consumed from @aaac/observability. * * event-catalog.md §1.5, §2.2 / OBSERVABILITY_TASKS.md Phase 1 / architecture.md §6, §7 */ /** Token usage metrics returned by LLM adapters after a query/session. */ interface TokenUsage { inputTokens: number; outputTokens: number; totalTokens?: number; cacheReadTokens?: number; cacheCreationTokens?: number; } /** Observability correlation ids propagated to spawned subprocesses. */ interface ObservabilityIds { /** Agent-axis session id (= the session/run envelope run_id). */ sessionId?: string; /** Distributed trace id, when available. */ traceId?: string; /** Execution run id (ExecutionEnvelope.run_id). */ runId?: string; } /** Environment variable names read by `.cursor/hooks/observ-record.sh`. */ declare const OBSERVABILITY_ENV_VARS: { readonly sessionId: "AAAC_SESSION_ID"; readonly traceId: "AAAC_TRACE_ID"; readonly runId: "AAAC_RUN_ID"; }; /** * Build a subprocess environment that propagates the active observability * correlation ids as AAAC_SESSION_ID / AAAC_TRACE_ID / AAAC_RUN_ID. * * When @aaac/runtime spawns `git` (directly via a toolchain check, or * indirectly through an agent shell), the git `post-commit` hook runs * `.cursor/hooks/observ-record.sh`, whose highest-priority session_id source is * `$AAAC_SESSION_ID` (#115). Propagating these ids lets the promotion.commit / * promotion.file events emitted by the hook correlate to the originating agent * session. * * Returns a shallow clone of {@link baseEnv}; only ids that are defined and * non-empty are set, so the child never inherits empty/stale values. */ declare function buildObservabilityEnv(ids: ObservabilityIds, baseEnv?: NodeJS.ProcessEnv): NodeJS.ProcessEnv; /** * Minimal observer emit signature — structurally matches EventCollector.emit(). * Pass `collector.emit.bind(collector)` to wire up the full observability pipeline. * When undefined, all emission is a no-op. */ type ObserverEmitFn = (event: EmitInput) => void; /** * Serialize writes through a shared in-process observer. * Concurrent workflow steps that emit in parallel can hit SQLITE_BUSY on the * shared SqliteSink without this guard. */ declare function serializeObserverEmit(emit: ObserverEmitFn): ObserverEmitFn; interface EnvelopeParams { /** run_id of the parent execution (populated by workflow-runner for task spans). */ parentRunId?: string; /** Component / agent identifier from the agent-contracts definition. */ componentId?: string; /** Agent that issued this execution (handoff source). */ fromAgent?: string; /** Agent that receives this execution (handoff target). */ toAgent?: string; /** agent-contracts schema version. */ contractVersion?: string; /** LLM adapter identifier (e.g. 'claude-agent-sdk'). */ adapter?: string; /** LLM model identifier (e.g. 'claude-opus-4-5'). */ model?: string; /** Task instance identifier within the run. */ taskInstanceId?: string; } /** * Create an ExecutionEnvelope with a fresh UUIDv7 run_id and current timestamp. * Only defined fields are included — undefined values are omitted. */ declare function createExecutionEnvelope(params?: EnvelopeParams): ExecutionEnvelope; /** * Emit an agent.session open span (root workflow/session execution). * * Uses envelope.run_id as the spanId so that child agent.subagent spans can * reference it as parentSpanId for hierarchical correlation. * * Returns the spanId emitted (= envelope.run_id). * Returns undefined when observer is undefined (no-op). * * event-catalog.md §2.2 — required: agent.session_id; axis: agent */ declare function emitSessionOpen(observer: ObserverEmitFn | undefined, envelope: ExecutionEnvelope, workflowId: string): string | undefined; /** * Emit an agent.session close span. * * `errorMessage` is set on the exception path (workflow body threw) so the * failure cause is recorded alongside the run status. Omitted on the normal path. * * event-catalog.md §2.2 — optional: agent.session.duration_ms, agent.status, agent.error */ declare function emitSessionClose(observer: ObserverEmitFn | undefined, spanId: string, envelope: ExecutionEnvelope, durationMs: number, status: string, errorMessage?: string): void; /** * Emit an agent.subagent open span (task/handoff execution). * * Uses envelope.run_id as the spanId and parentSpanId for hierarchical correlation * (typically the session span's run_id). * * Returns the spanId emitted (= envelope.run_id). * Returns undefined when observer is undefined (no-op). * * event-catalog.md §2.2 — required: agent.role; axis: agent */ declare function emitSubagentOpen(observer: ObserverEmitFn | undefined, envelope: ExecutionEnvelope, parentSpanId: string | undefined, taskId: string, agentRole: string, sessionId?: string): string | undefined; /** * Emit an agent.subagent close span. * * `errorMessage` records the failure cause on `agent.error` (parity with * emitSessionClose); it is omitted from the attributes when undefined. * * event-catalog.md §2.2 — optional: agent.duration_ms, agent.status, agent.error, * token_usage, cost_usd */ declare function emitSubagentClose(observer: ObserverEmitFn | undefined, spanId: string, envelope: ExecutionEnvelope, durationMs: number, status: string, agentRole: string, errorMessage?: string, sessionId?: string): void; /** * Emit an evaluate.iteration open span (one closed-loop iteration). * * Returns the spanId emitted (= generated UUIDv7). * Returns undefined when observer is undefined (no-op). */ declare function emitIterationOpen(observer: ObserverEmitFn | undefined, parentSpanId: string | undefined, evaluateTaskId: string, loopTo: string, iterationNumber: number, maxIterations: number): string | undefined; /** * Emit an evaluate.iteration close span. */ declare function emitIterationClose(observer: ObserverEmitFn | undefined, spanId: string, evaluateTaskId: string, iterationNumber: number, verdict: string, durationMs: number, feedbackInjected: boolean): void; /** * Emit an evaluate.metric instant event when an evaluate step terminates. */ declare function emitIterationMetric(observer: ObserverEmitFn | undefined, parentSpanId: string | undefined, evaluateTaskId: string, totalIterations: number, terminalOutcome: string): void; /** Options forwarded from task-runner to adapters for inner turn-level spans. */ interface InnerSpanOptions { observer?: ObserverEmitFn; parentSpanId?: string; /** * Agent-axis session id (= the enclosing agent.session run_id). Threaded so * inner agent.llm_turn / agent.tool_exec spans carry a non-NULL session_id and * join the cross-axis correlation rules (#143 / #140). */ sessionId?: string; } /** * Emit an agent.llm_turn open span when a new LLM turn begins. * * Returns the spanId emitted (= generated UUIDv7). * Returns undefined when observer is undefined (no-op). */ declare function emitLlmTurnOpen(observer: ObserverEmitFn | undefined, parentSpanId: string | undefined, turnNumber: number, model?: string, llmParams?: { temperature?: number; reasoningEffort?: string; }, sessionId?: string): string | undefined; /** * Emit an agent.llm_turn close span. */ declare function emitLlmTurnClose(observer: ObserverEmitFn | undefined, spanId: string, turnNumber: number, durationMs: number, tokenAttrs?: { inputTokens?: number; outputTokens?: number; cacheHitTokens?: number; toolCallsCount?: number; }, sessionId?: string): void; /** Optional emit-time attributes and links for agent.tool_exec spans (#151). */ interface ToolExecOpenOptions { sessionId?: string; extraAttributes?: Record; links?: CanonicalLink[]; } interface ToolExecCloseOptions { sessionId?: string; extraAttributes?: Record; outputSummary?: string; } /** * Emit an agent.tool_exec open span when a tool execution begins. * * Returns the spanId emitted (= generated UUIDv7). * Returns undefined when observer is undefined (no-op). */ declare function emitToolExecOpen(observer: ObserverEmitFn | undefined, parentSpanId: string | undefined, toolName: string, inputSummary: string, turnNumber: number, sessionIdOrOptions?: string | ToolExecOpenOptions): string | undefined; /** * Emit an agent.tool_exec close span. */ declare function emitToolExecClose(observer: ObserverEmitFn | undefined, spanId: string, toolName: string, durationMs: number, sessionIdOrOptions?: string | ToolExecCloseOptions): void; /** * Emit a toolchain.execution open span when a toolchain tool is invoked. * * Returns the spanId emitted (= generated UUIDv7). * Returns undefined when observer is undefined (no-op). */ declare function emitToolchainOpen(observer: ObserverEmitFn | undefined, parentSpanId: string | undefined, toolchainId: string, operation: string, artifactIds: string[], componentId?: string): string | undefined; /** * Emit a toolchain.execution close span. */ declare function emitToolchainClose(observer: ObserverEmitFn | undefined, spanId: string, toolchainId: string, operation: string, durationMs: number, status: "success" | "failure", errorMessage?: string): void; /** * Library Tool → SDK Function Tool conversion. * * Converts LibraryToolDefinition entries into SDK-native function tools * that each adapter can register with its respective LLM SDK. * * Each adapter receives tools in its native format: * - Claude Agent SDK: MCP tool via createSdkMcpServer + tool() * - OpenAI Agents SDK: function tool object * - Google ADK: FunctionDeclaration tool */ /** * Adapter-agnostic function tool descriptor. Adapters convert this * into their SDK-specific tool format. */ interface SdkFunctionTool { name: string; description: string; inputSchema: Record; handler: (args: Record) => Promise; } /** * Build adapter-agnostic function tool descriptors from a LibraryToolRegistry. * Each tool's handler calls registry.execute() and serialises the result. */ declare function buildSdkFunctionTools(registry: LibraryToolRegistry): SdkFunctionTool[]; interface LibraryToolDefinition { toolId: string; description: string; module: string; exportName: string; inputSchema?: Record; outputSchema?: Record; } interface LibraryToolRegistry { register(def: LibraryToolDefinition): void; get(toolId: string): LibraryToolDefinition | undefined; getAll(): LibraryToolDefinition[]; execute(toolId: string, input: unknown): Promise; } declare function createLibraryToolRegistry(): LibraryToolRegistry; /** * Create a LibraryToolRegistry backed by pre-built SdkFunctionTool handlers. * Unlike createLibraryToolRegistry (which resolves tools via dynamic import), * this variant delegates execute() directly to the tool's in-process handler. */ declare function createRegistryFromSdkTools(tools: SdkFunctionTool[]): LibraryToolRegistry; /** * ModelResolver — resolves a model_class to a concrete adapter + model pair. * * Resolution priority (highest wins): * 1. AGENT_RUNTIME_MODEL_{FAST|STANDARD|THINKING} env var * 2. AGENT_RUNTIME_MODEL env var (catch-all fallback) * 3. agents.conf.yaml model_mapping. * 4. CLI --adapter + adapter default model */ type ModelClass = "fast" | "standard" | "thinking"; interface ResolvedModel { adapter: string; model?: string; } interface ModelResolver { resolve(modelClass: ModelClass | undefined): ResolvedModel; } interface ModelMappingConfig { fast?: { adapter: string; model?: string; }; standard?: { adapter: string; model?: string; }; thinking?: { adapter: string; model?: string; }; } interface ModelResolverOptions { modelMapping?: ModelMappingConfig; fallbackAdapter: string; fallbackModel?: string; env?: Record; /** * When set, always use this adapter name. Model is still resolved per class * from mapping / env (e.g. CLI `--adapter mock` with project model_mapping). */ pinnedAdapter?: string; } declare function createModelResolver(options: ModelResolverOptions): ModelResolver; /** * Toolchain Checker — runs check commands defined in toolchain-contracts * and returns structured pass/fail results. * * Each toolchain may declare a `checks` map (checkType → shell command). * This module iterates all checks, executes them via subprocess, and * returns a ToolchainCheckResult[]. * * For "drift" check types, a manifest-based fast path is available: * if a .toolchain-manifest.json exists and the toolchain_id matches, * the command execution can be skipped when the source hash is current. */ declare const ToolchainManifestSchema: z.ZodObject<{ schema: z.ZodString; toolchain_id: z.ZodString; generated_at: z.ZodString; source_hash: z.ZodString; output_hash: z.ZodString; source_globs: z.ZodOptional>; output_globs: z.ZodOptional>; files: z.ZodOptional>>; }, z.core.$strip>; type ToolchainManifest = z.infer; interface ToolchainCheckResult { toolchainId: string; checkType: string; status: "pass" | "fail" | "skip" | "error"; action: "block" | "warn" | "shadow"; message?: string; durationMs?: number; } interface RunToolchainChecksOptions { /** Absolute path to toolchain-contracts YAML */ toolchainsPath: string; /** Absolute path to artifact-contracts YAML (optional, for manifest fast path) */ artifactsPath?: string; /** Working directory for subprocess execution */ cwd?: string; /** Filter: only run these check types */ checkTypes?: string[]; /** Filter: only run checks for these toolchain IDs */ toolchainFilter?: string[]; /** Policy-resolved action per check type. Key = check type, value = action. Special key "_default" for fallback. */ checkTypeActions?: Record; /** Default action when no policy match */ defaultAction?: "block" | "warn" | "shadow"; /** * Optional observer emit function. When provided, each check execution emits a * toolchain.execution span (open before the check, close after) so the check is * recorded on the agent axis. No-op when undefined (observer is optional). * This is OBSERVATION ONLY — emitting spans never alters the returned results * nor the resolved action, so workflow success/failure semantics are unchanged. */ observer?: ObserverEmitFn; /** Parent span id (typically the enclosing agent.session run_id) for correlation. */ parentSpanId?: string; /** Component id recorded on toolchain.execution spans (agent.component_id). */ componentId?: string; /** * Observability correlation ids propagated to spawned check subprocesses as * AAAC_SESSION_ID / AAAC_TRACE_ID / AAAC_RUN_ID (#115). A check that spawns * `git commit`/`git push` lets the resulting git `post-commit` hook attribute * its promotion.* events back to this session. No-op when undefined. */ observabilityIds?: ObservabilityIds; } declare function runToolchainChecks(options: RunToolchainChecksOptions): Promise; /** * Workflow Runner — orchestrates a DSL workflow as a sequence of task executions * * Programmatic control flow that replaces LLM-driven step interpretation: * * 1. Load workflow contract (ordered steps) * 2. Run plugin beforeWorkflow hooks * 3. For each step: * - delegate → call task-runner with followUp/retry recovery * - gate → pause and wait for user input * 4. Validate each result against handoff schema * 5. Accumulate context between steps * 6. Run plugin afterWorkflow hooks */ /** * A factory that creates independent SdkAdapter instances. * Used by runWorkflow to allocate one adapter per parallel step, * avoiding session-level serialization in stateful SDK adapters. */ type SdkAdapterFactory = () => SdkAdapter; /** * Model-aware adapter factory. Accepts a model_class and returns an adapter * configured for that capability level (possibly a different provider/model). */ type ModelAwareSdkAdapterFactory = (modelClass?: ModelClass) => SdkAdapter | Promise; /** Accepts either a single adapter (serial/shared) or a factory (parallel-safe). */ type AdapterOrFactory = SdkAdapter | SdkAdapterFactory | ModelAwareSdkAdapterFactory; /** Specification for what a step receives from a dependency. */ interface ReceiveSpec { /** The task id of the dependency step to receive from. If omitted, alias is used as task id. */ readonly from?: string; /** JSONPath-like dotted path to extract from the step result (e.g. "$.changed_files"). Simplified: just use dot notation like "changed_files" or "checks_performed". If omitted, entire result is received. */ readonly path?: string; } interface DelegateStep { readonly type: "delegate"; readonly task: string; readonly from_agent: string; readonly description: string; readonly optional: boolean; readonly max_retries: number; readonly max_follow_ups?: number; readonly depends_on?: readonly string[]; readonly instruction?: string; readonly receives?: Record; readonly retry?: { readonly condition: string; readonly fix_task: string; readonly revalidate_task?: string; }; } interface GateStep { readonly type: "gate"; readonly gate_kind: string; readonly description: string; readonly depends_on?: readonly string[]; } /** * Evaluate step — runs a task that returns a convergence-envelope, then either * proceeds (verdict=pass) or loops back to `loop_to` with feedback injected * (verdict=fail, iteration < max_iterations), or applies `on_exhausted`. */ interface EvaluateStep { readonly type: "evaluate"; readonly task: string; readonly from_agent: string; readonly evaluator_agent?: string; readonly description?: string; readonly loop_to: string; readonly max_iterations: number; readonly inject_as?: string; readonly on_exhausted?: "abort" | "fail_partial" | "escalate"; readonly depends_on?: readonly string[]; } /** * Payload returned by an evaluate task in a convergence-envelope handoff. * The runtime reads `verdict` to decide whether to proceed or loop back. */ interface ConvergenceEnvelopePayload { /** "pass" means quality gate passed; "fail" triggers a loop-back. */ readonly verdict: "pass" | "fail"; /** Human-readable feedback injected into the next iteration via `inject_as`. */ readonly feedback?: string; } /** Typed handoff envelope produced by an evaluate task. */ type ConvergenceEnvelope = HandoffInput<"convergence-envelope", ConvergenceEnvelopePayload>; type WorkflowStep = DelegateStep | GateStep | EvaluateStep; interface WorkflowContractLike { readonly id: string; readonly description: string; readonly steps: readonly WorkflowStep[]; } interface WorkflowRunOptions { user_request: string; /** Override max follow-up attempts per step (lightweight output-format correction). Default: 2 */ maxFollowUps?: number; /** Override max full retry attempts per step. Default: from DSL step.max_retries */ maxRetries?: number; /** Variables propagated to every TaskContext in the workflow (from WorkflowInvocation.context). */ variables?: Record; onGate?: (gateKind: string, description: string, stepResults: StepResult[]) => Promise; onStepComplete?: (event: StepCompleteEvent) => void; onOptionalStep?: (step: DelegateStep, context: TaskContext) => Promise; /** * Writable stream for real-time progress output during agent execution. * Intermediate events from adapters are formatted and written here. * Typical value: process.stderr. */ progressOutput?: { write(chunk: string): unknown; }; /** * Optional observer emit function for agent-axis spans (agent.session, agent.subagent). * When undefined, no spans are emitted (observer is optional — no-op). * Pass EventCollector.emit.bind(collector) to wire up the full observability pipeline. */ observer?: ObserverEmitFn; /** * Optional toolchain-check observation config. When set together with `observer`, * runWorkflow runs the configured toolchain checks AFTER the workflow body (a * single post-run observation pass) and emits one toolchain.execution span per * check, correlated to this run's agent.session span. * * OBSERVATION ONLY (non-destructive): the checks never alter the WorkflowResult * — a failing check does not fail the workflow. `observer` and `parentSpanId` * are injected by runWorkflow; callers supply `toolchainsPath` (+ optional * artifactsPath/cwd/policy actions). */ toolchain?: RunToolchainChecksOptions; /** * In-process library tools to register with every task in this workflow. * Passed through to each runTask() call. Adapters convert these to their * native tool format (Claude MCP, OpenAI function tools, ADK tools). */ libraryTools?: LibraryToolRegistry; /** * Resolves adapter + model for execution envelopes (agent.session / agent.subagent). * When undefined, envelopes omit adapter/model (observer spans lack gen_ai attrs). */ resolveModelMeta?: (modelClass?: ModelClass) => ResolvedModel; } /** Typed handoff envelope for workflow input. */ interface HandoffInput { readonly type: TType; readonly version?: number; readonly payload: TPayload; } /** * Standard runtime invocation envelope. SDK-specific options (openaiThreadId, * sessionId, etc.) belong on the adapter constructor — not here. */ interface WorkflowInvocation { workflow: string; /** Structured typed handoff input. Takes precedence over user_request if both are set. */ handoff?: HandoffInput; /** Simple string input (convenience shorthand). */ user_request?: string; runtime?: { maxFollowUps?: number; maxRetries?: number; timeoutMs?: number; readonly?: boolean; dryRun?: boolean; }; hooks?: { onStepComplete?: (event: StepCompleteEvent) => void; onGate?: (gateKind: string, description: string, stepResults: StepResult[]) => Promise; onOptionalStep?: (step: DelegateStep, context: TaskContext) => Promise; }; /** * Writable stream for real-time progress output during agent execution. * Intermediate events from adapters are formatted and written here. * Typical value: process.stderr. */ progressOutput?: { write(chunk: string): unknown; }; context?: { cwd?: string; environment?: "local" | "ci" | "remote"; artifacts?: Record; variables?: Record; }; /** * Optional observer emit function for agent-axis spans (agent.session, agent.subagent). * When undefined, no spans are emitted (observer is optional — no-op). * Pass EventCollector.emit.bind(collector) to wire up the full observability pipeline. */ observer?: ObserverEmitFn; /** * Optional toolchain-check observation config (see WorkflowRunOptions.toolchain). * OBSERVATION ONLY — never changes the workflow outcome. */ toolchain?: RunToolchainChecksOptions; /** * In-process library tools to register with every task in this workflow. * Created once per execution and shared across all steps. */ libraryTools?: LibraryToolRegistry; /** * Resolves adapter + model for execution envelopes. Injected by executeWorkflow; * not typically set by external callers. */ resolveModelMeta?: (modelClass?: ModelClass) => ResolvedModel; } interface StepResult { step_index: number; task_id?: string; gate_kind?: string; outcome: TaskOutcome | { status: "gate_approved"; } | { status: "gate_rejected"; } | { status: "skipped"; }; follow_ups_used: number; retries_used: number; elapsed_ms: number; /** Resolved model_class for delegate/evaluate steps (from task registry). */ model_class?: ModelClass; /** Concrete adapter name used for this step's LLM calls. */ adapter?: string; /** Concrete model name used for this step's LLM calls. */ model?: string; } interface StepCompleteEvent { workflow_id: string; step_index: number; step_type: "delegate" | "gate" | "evaluate"; task_id?: string; gate_kind?: string; outcome_status: string; follow_ups_used: number; retries_used: number; elapsed_ms: number; } interface WorkflowResult { workflow_id: string; status: "completed" | "escalated" | "gate_rejected" | "error"; steps: StepResult[]; total_elapsed_ms: number; escalation_reason?: string; error_message?: string; } interface WorkflowRegistries { workflowRegistry?: Record; taskRegistry?: Record; agentRegistry?: Record; handoffSchemas?: Record; } /** @deprecated Use the WorkflowInvocation overload for typed handoff input. */ declare function runWorkflow(adapter: AdapterOrFactory, workflowId: string, options: WorkflowRunOptions, registries?: WorkflowRegistries): Promise; /** Structured invocation with typed handoff envelope. */ declare function runWorkflow(adapter: AdapterOrFactory, invocation: WorkflowInvocation, registries?: WorkflowRegistries): Promise; declare function buildGateEvaluationPrompt(step: GateStep, priorContext: string): string; declare function parseGateEvaluationResponse(response: string): boolean; /** * BoundResolver — runtime binding + policy resolution with per-agent isolation. * * Resolves artifact binding and guardrail/policy in one pass at runtime, * producing a per-agent scoped ResolvedComponent. Reuses existing * resolveBound(), buildGuardrailContext(), and agent scope resolution. */ interface ArtifactBindingConfig { source: string; mappings?: Record; } interface BoundResolveOptions { /** Component identifier — used for cache keying. */ id: string; /** Pre-resolved DSL (e.g. embedded from codegen). */ embeddedDsl?: Record; /** Path to DSL file — resolved via agent-contracts when no embeddedDsl. */ dslPath?: string; /** Paths to software binding YAML files (guardrail_impl, etc.). */ bindingPaths?: string[]; /** Active guardrail policy name from DSL guardrail_policies. */ activeGuardrailPolicy?: string; /** Artifact binding config — resolved via agent-contracts resolveBound(). */ artifactBinding?: ArtifactBindingConfig; /** Path substitutions for artifact binding. */ paths?: Record; /** Path to toolchain-contracts.yaml. */ toolchainContractsPath?: string; } interface ResolvedToolchain { id: string; kind: "library" | "cli" | "component"; description?: string; module?: string; command?: string; cli_contract?: string; component_contract?: string; artifacts: { consumes: string[]; produces: string[]; }; operations?: string[]; source: "toolchain-contracts" | "agent-contracts" | "merged"; } interface ResolvedComponent { id: string; dsl: Record; registries: WorkflowRegistries; guardrails: { perAgent: Map; }; diagnostics: Array<{ path?: string; message: string; severity?: string; }>; toolchains?: Record; toolchainsByAgent?: Map; } /** * Effective guardrail IDs for an agent: entity-side bindings ∪ scope-side bindings. */ declare function getEffectiveGuardrailIds(dsl: Record, agentId: string): Set; declare function guardrailContextToRuleData(ctx: GuardrailContext, effectiveIds?: Set): GuardrailRuleData; declare function buildPerAgentGuardrails(dsl: Record, guardrailCtx: GuardrailContext): Map; declare function deriveToolchainsForAgents(dsl: Record, toolchains: Record): Map; declare class BoundResolver { private readonly cache; /** * Resolve binding + policy in one pass. Results are cached by component id. */ resolve(opts: BoundResolveOptions): Promise; /** Clear cached components (e.g. for testing). */ clearCache(): void; } /** * Get guardrail rules for a specific agent from a ResolvedComponent. * Falls back to embedded _guardrailRules when no per-agent rules exist. */ declare function getGuardrailRulesForAgent(component: ResolvedComponent, agentId: string, fallbackDsl?: Record): GuardrailRuleData | undefined; /** * Candidate Agents — backend-neutral bridge for LLM-internal routing (model B) * * The runtime registers a set of *candidate sub-agents* with the SDK so the * entry/main agent's LLM can delegate to them internally via the SDK's native * subagent mechanism: * * - Claude `Options.agents: Record` * - OpenAI `Agent.handoffs: Agent[]` * - ADK `LlmAgent.subAgents: BaseAgent[]` * * `CandidateAgent` is the common, SDK-independent contract. Each adapter maps it * onto its provider's native shape. The selection rule (which agents become * candidates) lives here so all adapters stay backend-agnostic. */ /** * SDK-independent description of a sub-agent the entry agent's LLM may delegate * to. Adapters translate this into their provider's native subagent shape. */ interface CandidateAgent { /** Agent id (used as the SDK subagent key / name). */ name: string; /** When to use this agent — the routing hint shown to the delegating LLM. */ description: string; /** The agent's system prompt (role / purpose / responsibilities / constraints / rules). */ prompt: string; /** Optional allowed tool names (omit to inherit from the parent agent). */ tools?: string[]; /** Optional model id (omit to inherit from the parent agent). */ model?: string; } /** * Render an agent contract into its system-prompt string: the static * Role / Responsibilities / Constraints / Rules sections. * * Shared by `buildSplitTaskPrompt` (entry agent system prompt) and * `buildCandidateAgents` (each candidate's `prompt`) so both stay in sync. */ declare function renderAgentSystemPrompt(agent: AgentContractLike): string; interface BuildCandidateAgentsOptions { /** The entry/main agent id. Excluded from the candidate set. */ entryAgentId?: string; /** * When provided (typically the entry agent's `can_invoke_agents`), restrict * candidates to these agent ids. Omit to allow every non-entry agent. */ allowedAgentIds?: readonly string[]; toolchainsByAgent?: Map; } /** * Build the candidate sub-agent set from an agent registry. * * Selection rule: every agent EXCEPT the entry agent; if `allowedAgentIds` is * given, further restrict to that allow-list. */ declare function buildCandidateAgents(agentRegistry: Record, opts?: BuildCandidateAgentsOptions): CandidateAgent[]; /** * Task Runner — runs a single DSL task via an SDK agent * * Responsibilities: * 1. Resolve task contract → target agent contract * 2. Build the agent prompt from contract + context * 3. Apply plugin prompt enhancers and beforeTask hooks * 4. Send to SDK agent (via abstract SdkAdapter) and stream result * 5. Parse + validate result against handoff schema * 6. Apply plugin afterTask hooks * 7. Return typed result or escalation signal * * Two recovery strategies: * - followUp: lightweight, same session — fix output format only * - retry: heavyweight, new session — re-execute entire task */ interface AgentContractLike { readonly id: string; readonly role_name: string; readonly purpose: string; readonly mode: "read-write" | "read-only"; readonly responsibilities: readonly string[]; readonly constraints: readonly string[]; readonly rules?: readonly { readonly id: string; readonly description: string; readonly severity: string; }[]; /** * Agent ids this agent is allowed to delegate to. When present, it restricts * the candidate sub-agent set registered with the SDK for LLM-internal routing. */ readonly can_invoke_agents?: readonly string[]; /** * Tool names this agent may execute. When present, sub-agents receive an * isolated tool set instead of inheriting the parent agent's tools. */ readonly can_execute_tools?: readonly string[]; } interface TaskContractLike { readonly id: string; readonly description: string; readonly target_agent: string; readonly result_handoff: string; readonly completion_criteria: readonly string[]; readonly model_class?: "fast" | "standard" | "thinking"; /** * When true, the adapter may enable Dynamic Workflow tools (e.g. Claude's * Workflow tool) so the agent can internally parallelise sub-tasks. * Handoff validation at the task boundary is still enforced. */ readonly allow_dynamic_workflow?: boolean; } /** * Progress event emitted by adapters during agent execution. * Enables real-time visibility into what the agent is doing * (tool calls, text output, status changes). */ interface AgentProgressEvent { type: "tool_use" | "tool_result" | "text" | "status" | "cache_metrics"; tool_name?: string; /** Tool invocation arguments (e.g. file path, command). */ input?: Record; message?: string; /** SDK session ID for correlating events within a single adapter call. */ session_id?: string; /** Cache utilization metrics from the SDK response. */ cacheMetrics?: { cachedInputTokens?: number; totalInputTokens?: number; }; } /** * A prompt split into static (cacheable) and dynamic (per-invocation) sections. * Adapters that support prompt caching can use the `system` sections as * provider-specific system prompts, reducing token costs on repeated calls. */ interface SplitPrompt { /** Static sections: role, responsibilities, constraints, rules, task, schema, recovery. */ system: string[]; /** Dynamic sections: user request, handoff input, prior context, files, acceptance criteria. */ user: string; } /** * Optional cache configuration for adapters that support prompt caching. * Provider-specific defaults apply when individual fields are omitted. */ interface CacheConfig { /** Enable prompt caching. Defaults to true when the adapter supports it. */ enabled?: boolean; /** Provider-specific TTL (e.g. "5m", "1h", "24h"). */ ttl?: string; /** Stable key for cross-session cache reuse (provider-specific). */ cacheKey?: string; } /** * Base options for SdkAdapter.send(). SDK-specific options (model, cwd, * sessionMode, etc.) belong on the adapter constructor / factory — not here. */ interface AdapterSendOptions { readonly: boolean; /** * Optional callback invoked with intermediate progress events during execution. * Adapters that consume an internal event stream (e.g. Claude SDK's AsyncGenerator) * call this for each non-result message, enabling callers to display live progress. */ onProgress?: (event: AgentProgressEvent) => void; /** * Split prompt for prompt caching support. When provided, adapters that support * caching can separate static (cacheable) instructions from dynamic content. * Adapters without caching support can ignore this and use the prompt argument. */ splitPrompt?: SplitPrompt; /** * Candidate sub-agents the entry agent's LLM may delegate to (model B, * LLM-internal routing). Adapters register these via their native subagent * mechanism (Claude `agents`, OpenAI `handoffs`, ADK `subAgents`). When * omitted or empty, adapters behave exactly as before (single agent). */ agents?: CandidateAgent[]; /** * When true, adapters that support dynamic workflow tools (e.g. Claude's * Workflow tool for agent()/pipeline()/parallel()) should enable them. * The task's final output is still validated against the handoff schema. */ allowDynamicWorkflow?: boolean; /** * In-process library tools to register with the SDK as function tools. * Adapters convert these to their native tool format (Claude MCP, OpenAI * function tools, ADK tools). I/O is validated against the tool's schemas. */ libraryTools?: LibraryToolRegistry; /** * Optional observer emit function for inner turn-level spans * (agent.llm_turn, agent.tool_exec). When undefined, adapters skip * instrumentation entirely (no-op). */ observer?: ObserverEmitFn; /** * Parent span ID for inner turn-level spans. Typically the subagent span ID * so that LLM turn and tool execution spans are correlated as children. */ parentSpanId?: string; /** * Agent-axis session id (= the enclosing agent.session run_id). Threaded so * inner agent.llm_turn / agent.tool_exec spans carry a non-NULL session_id and * join the cross-axis correlation rules (#143 / #140). */ sessionId?: string; } /** * Rich execution request for adapters that need more than a prompt string. * Adapters can implement sendExecution() to receive full contract context. */ interface AgentExecutionRequest { agentId: string; taskId: string; prompt: string; handoff?: { type: string; payload: unknown; }; schema?: { handoffType: string; zodSchema: unknown; promptDescription: string; }; context: TaskContext; /** Resumable memory reference from a previous run. */ memoryRef?: MemoryRef; /** * Split prompt for prompt caching support. When provided, adapters can * separate static instructions (system) from dynamic content (user). */ splitPrompt?: SplitPrompt; /** * Candidate sub-agents for LLM-internal routing (model B). Mirrors * `AdapterSendOptions.agents`; also forwarded via `options.agents`. */ agents?: CandidateAgent[]; options: AdapterSendOptions & { maxFollowUps: number; attempt: number; }; } interface SdkAdapter { /** Start a new task session and return the full text response. */ send(prompt: string, options: AdapterSendOptions): Promise; /** * Send a follow-up message within the same agent session. * Used for output-format corrections without re-executing the task. * Falls back to send() if not implemented (stateless adapters like mock). */ followUp?(message: string): Promise; /** * Rich execution path. When implemented, the runtime prefers this over * send() and passes the full contract context. Adapters that only need * a prompt string can ignore this — the runtime falls back to send(). */ sendExecution?(request: AgentExecutionRequest): Promise; /** Return the memory_ref produced by the last send/sendExecution call. */ getLastMemoryRef?(): MemoryRef | null; /** Return the token usage from the last send/sendExecution call. */ getLastTokenUsage?(): TokenUsage | null; /** Check if this adapter is compatible with the given compat tag. */ isCompatible?(compat: string): boolean; } interface TaskContext { user_request: string; prior_context?: string; relevant_paths?: string[]; acceptance_criteria?: string[]; /** * Structured handoff input (primary data). When present, prompt builders * should derive the prompt from this rather than user_request alone. */ handoff_input?: { type: string; version?: number; payload: unknown; }; /** Arbitrary structured variables plugins or workflow context may inject. */ variables?: Record; /** Resumable memory reference from a previous run. */ memoryRef?: MemoryRef; } type TaskOutcome = { status: "success"; data: unknown; raw: string; memoryRef?: MemoryRef; } | { status: "validation_error"; errors: z.ZodError; raw: string; } | { status: "escalation"; reason: string; raw: string; } | { status: "error"; message: string; }; /** * Retry strategy decision. * * - "follow_up": lightweight — same session, fix output format only * - "retry": heavyweight — new send(), re-execute the entire task * - "abort": stop retrying, return the current outcome */ type RetryDecision = "follow_up" | "retry" | "abort"; interface TaskRunOptions { /** Max follow-up attempts (output format correction, same session). Default: 2 */ maxFollowUps?: number; /** Max full retry attempts (re-execute entire task via send). Default: 0 */ maxRetries?: number; /** * Called on each failure to decide which recovery strategy to use. * Default: validation_error → follow_up, empty output → retry, else abort. */ decideRetryStrategy?: (outcome: TaskOutcome, counts: { followUps: number; retries: number; }) => Promise | RetryDecision; /** * Writable stream for real-time progress output during agent execution. * When provided, intermediate adapter events (tool use, status, etc.) * are formatted and written here. Typical value: process.stderr. */ progressOutput?: { write(chunk: string): unknown; }; /** * Optional observer emit function for agent-axis spans (agent.subagent open/close). * When undefined, no spans are emitted (observer is optional — no-op). * Pass EventCollector.emit.bind(collector) to wire the full observability pipeline. */ observer?: ObserverEmitFn; /** * Parent span ID (typically the enclosing agent.session span's run_id). * Used to correlate agent.subagent spans with their parent session. */ parentSpanId?: string; /** * Agent-axis session id (= the enclosing agent.session run_id). Threaded from * the workflow runner so the subagent span and all inner spans share one * non-NULL session_id, even when parentSpanId is an evaluate iteration span * rather than the session span (#143 / #140). */ sessionId?: string; /** LLM adapter identifier for the execution envelope (gen_ai.system). */ envelopeAdapter?: string; /** LLM model identifier for the execution envelope (gen_ai.request.model). */ envelopeModel?: string; } interface TaskRunResult { outcome: TaskOutcome; follow_ups_used: number; retries_used: number; tokenUsage?: TokenUsage; } /** * Convert a Zod schema into a human-readable field table for inclusion in LLM prompts. * Recursively generates sub-tables for nested objects and array elements. */ declare function zodSchemaToPromptDescription(schema: z.ZodType): string; /** * Generate a YAML example from a Zod schema shape, recursively expanding * nested objects and arrays up to a configurable depth. */ declare function zodSchemaToYamlExample(schema: z.ZodType, maxDepth?: number): string; /** * Duck-type check: does `value` look like a ProjectNavigationIndex? * Requires a `system` object and an `artifacts` record. */ declare function isNavigationIndex(value: unknown): value is Record; /** * Render the Level 1 navigation index as a compact prompt section — a * human-readable SUMMARY of artifacts (type, authority, edit policy, key * relations and owning agents), NOT a raw JSON dump. Gives the agent a map of * the project's artifacts so it can navigate before acting. */ declare function renderNavigationIndexPrompt(navigationIndex: Record): string; /** Collect analyzer.* tool ids from a wired library tool registry. */ declare function collectAnalyzerToolIds(registry?: LibraryToolRegistry): string[]; /** * Level 1 exploration mandate applies when the runtime injected a navigation * index (codebase map) — the signal that artifact-scoped investigation is active. */ declare function shouldInjectAnalyzerExplorationMandate(context: TaskContext): boolean; /** * System-prompt section mandating analyzer MCP tools before ad-hoc file reads. * Injected automatically by runTask when Level 1 context is present. */ declare function renderAnalyzerExplorationMandatePrompt(toolIds: readonly string[]): string; interface PromptBuilderOptions { handoffSchemas?: Record; retry?: { condition: string; fix_task: string; revalidate_task?: string; }; /** When set, injects Level 1 analyzer exploration mandate into the system prompt. */ analyzerExploration?: { toolIds: readonly string[]; }; } /** * Build a prompt split into static (cacheable) and dynamic (per-invocation) parts. * * Static (system): Role, Responsibilities, Constraints, Rules, Task description, * Completion Criteria, Output Format / Schema, Recovery Instructions. * * Dynamic (user): User Request, Handoff Input, Prior Context, * Relevant Files, Acceptance Criteria. */ declare function buildSplitTaskPrompt(agent: AgentContractLike, task: TaskContractLike, context: TaskContext, options?: PromptBuilderOptions): SplitPrompt; declare function buildTaskPrompt(agent: AgentContractLike, task: TaskContractLike, context: TaskContext, options?: PromptBuilderOptions): string; declare function extractStructuredResult(raw: string): unknown | null; declare function buildRetryFollowUp(task: TaskContractLike, lastOutcome: TaskOutcome, options?: PromptBuilderOptions): string; declare function runTask(adapter: SdkAdapter, taskId: string, context: TaskContext, options?: TaskRunOptions & { agentRegistry?: Record; taskRegistry?: Record; handoffSchemas?: Record; retry?: { condition: string; fix_task: string; revalidate_task?: string; }; libraryTools?: LibraryToolRegistry; }): Promise; export { type ToolchainManifest as $, type AdapterSendOptions as A, type BoundResolveOptions as B, type CacheConfig as C, type DelegateStep as D, type EnvelopeParams as E, type ModelResolver as F, type GateStep as G, type HandoffInput as H, InMemoryStore as I, type ModelResolverOptions as J, OBSERVABILITY_ENV_VARS as K, type LibraryToolRegistry as L, type MemoryRef as M, type ObservabilityIds as N, type ObserverEmitFn as O, type PromptBuilderOptions as P, type ReceiveSpec as Q, type ResolvedComponent as R, type SdkAdapter as S, type TokenUsage as T, type ResolvedModel as U, type RetryDecision as V, type WorkflowResult as W, type SdkAdapterFactory as X, type SplitPrompt as Y, type TaskRunOptions as Z, type ToolchainCheckResult as _, type AgentExecutionRequest as a, ToolchainManifestSchema as a0, type WorkflowContractLike as a1, type WorkflowInvocation as a2, type WorkflowRunOptions as a3, type WorkflowStep as a4, buildCandidateAgents as a5, buildGateEvaluationPrompt as a6, buildObservabilityEnv as a7, buildPerAgentGuardrails as a8, buildRetryFollowUp as a9, isNavigationIndex as aA, parseGateEvaluationResponse as aB, renderAgentSystemPrompt as aC, renderAnalyzerExplorationMandatePrompt as aD, renderNavigationIndexPrompt as aE, runTask as aF, runToolchainChecks as aG, runWorkflow as aH, serializeObserverEmit as aI, shouldInjectAnalyzerExplorationMandate as aJ, zodSchemaToPromptDescription as aK, zodSchemaToYamlExample as aL, buildSdkFunctionTools as aa, buildSplitTaskPrompt as ab, buildTaskPrompt as ac, collectAnalyzerToolIds as ad, createExecutionEnvelope as ae, createLibraryToolRegistry as af, createModelResolver as ag, createRegistryFromSdkTools as ah, deriveToolchainsForAgents as ai, emitIterationClose as aj, emitIterationMetric as ak, emitIterationOpen as al, emitLlmTurnClose as am, emitLlmTurnOpen as an, emitSessionClose as ao, emitSessionOpen as ap, emitSubagentClose as aq, emitSubagentOpen as ar, emitToolExecClose as as, emitToolExecOpen as at, emitToolchainClose as au, emitToolchainOpen as av, extractStructuredResult as aw, getEffectiveGuardrailIds as ax, getGuardrailRulesForAgent as ay, guardrailContextToRuleData as az, type SdkFunctionTool as b, type TaskContext as c, type TaskOutcome as d, type AgentContractLike as e, type TaskContractLike as f, type WorkflowRegistries as g, type StepCompleteEvent as h, type StepResult as i, type MemoryStore as j, type ArtifactBindingConfig as k, type RunToolchainChecksOptions as l, type ModelMappingConfig as m, type TaskRunResult as n, type ResolvedToolchain as o, type LibraryToolDefinition as p, type AdapterOrFactory as q, type AgentProgressEvent as r, BoundResolver as s, type CandidateAgent as t, type ConvergenceEnvelope as u, type ConvergenceEnvelopePayload as v, type EvaluateStep as w, type InnerSpanOptions as x, type ModelAwareSdkAdapterFactory as y, type ModelClass as z };