Skip to main content

Agent Runtime API

Table of Contents

Top

upsquad/runtime/v1/runtime.proto

AskUserResume

AskUserResume carries a resolved agent-initiated ask_user answer back into a worker turn so it resumes IN-CONTEXT (AIU-3, #2320). It is distinct from the approval-interrupt resume (InitWorkerSession.resume_checkpoint) because an ask_user is an ELICITATION, not a gated side-effect: there is no MCP proxy egress to dedup and no approval decision — only a human answer to splice as the ask_user tool's result.

FieldTypeLabelDescription
checkpointbytescheckpoint is the frozen in-step batch the worker emitted on the input_required event (InputRequired.checkpoint) — the JSON snapshot of the mid-turn state (messages incl. the ask_user tool_use, the pending current_tool_calls, and the executed-sibling tool_results). Opaque to the orchestrator/interpreter: it rides the Temporal activity boundary verbatim and is handed back here unchanged so the worker restores exactly the frozen turn. Never persisted; never carries provider keys or bearers (stripped at emit, exactly like CheckpointEvent).
answer_tool_resultbytesanswer_tool_result is the synthesized ask_user tool_result the worker splices onto the resumed turn: a compact JSON object {tool_call_id, result} where tool_call_id is the pending ask_user call and result is the human's answer envelope ({choice, text, answered_by}). The Go interpreter builds it deterministically from the durable prompt row's response_payload (AIU-3), so the same bytes resume the turn whether the answer arrived via the signal, the AlreadyAnswered dedup, or the re-poll.

CheckpointEvent

CheckpointEvent carries a serialized LangGraph state snapshot for persistence and session recovery.

FieldTypeLabelDescription
statebytesstate is the serialized LangGraph state bytes.
hashstringhash is the SHA-256 hex digest of the state bytes.
created_atgoogle.protobuf.Timestampcreated_at is when the checkpoint was created.

CheckpointRequest

CheckpointRequest carries a worker-produced LangGraph state snapshot that the Orchestrator must persist to agent_checkpoints for resume.

The Orchestrator-facing side of this RPC (worker → orchestrator) receives the opaque bytes blob; the Worker-facing side (orchestrator → worker) may also use this request with only session_id set as a "please serialise and return state" poll. The two surfaces share the proto definition; which fields are populated depends on direction.

Delta §5.2 / OQ-5: the bytes blob carries a 4-byte big-endian schema version prefix produced by internal/runtime/checkpointstore; the Python resume path (#174) mirrors the same header format.

FieldTypeLabelDescription
session_idstringsession_id is the UUID of the session being checkpointed.
bytesbytesbytes is the opaque LangGraph state blob with a 4-byte big-endian schema version prefix. Populated on the worker → orchestrator path.
bytes_sha256stringbytes_sha256 is the SHA-256 hex digest of bytes (including the schema version prefix). Used by the orchestrator for an integrity check on duplicate-key retry (OQ-3). Populated on the worker → orchestrator path.
loop_iterationint32loop_iteration is the worker's monotonic iteration counter for this session. It forms the upsert key together with session_id — a duplicate (session_id, loop_iteration) with matching hash is the idempotent replay path (OQ-3). Populated on the worker → orchestrator path.

CheckpointResponse

CheckpointResponse carries the serialized worker state.

FieldTypeLabelDescription
statebytesstate is the serialized LangGraph state bytes.
hashstringhash is the SHA-256 hex digest of the state bytes.

CompletionEvent

CompletionEvent signals the step has finished with a final response.

FieldTypeLabelDescription
final_responsestringfinal_response is the agent's complete response text.
token_usageTokenUsagetoken_usage contains the aggregated token counts and cost for this step.
loop_iterationsint32loop_iterations is the number of think-act-observe iterations performed.
duration_msint32duration_ms is the total wall-clock time for the step.

ContentPatternProto

ContentPatternProto is the wire representation of a user-defined or platform-defined regex pattern for serialization to the Python worker. LLD: #208 Section 13.

FieldTypeLabelDescription
idstringid is the unique pattern identifier.
regexstringregex is the regular expression to match.
severitystringseverity is the action on match: "block", "redact", "log_only".
categorystringcategory classifies the pattern: "injection", "secret", "pii", "custom".
descriptionstringdescription is a human-readable pattern description.

DecompositionEvent

DecompositionEvent carries the structured multi-step plan the worker produced on the autonomous PLAN step. The orchestrator parses todos into Plan.Todos (re-indexing ids and clamping to its MaxTodos bound); todos MAY be empty, in which case the orchestrator keeps its single seed todo and pursues the goal directly (safe degrade). See the T4 PLAN-result parser (#1614).

FieldTypeLabelDescription
todosTodoSpecrepeatedtodos is the ordered sub-goal list. May be empty.

ErrorEvent

ErrorEvent signals a recoverable or terminal error during step execution.

FieldTypeLabelDescription
codestringcode is a machine-readable error code (e.g., "LLM_RATE_LIMIT").
messagestringmessage is a human-readable error description.
retryableboolretryable indicates whether the caller should retry this step.
detailstringdetail contains additional diagnostic information.

ExecuteStepEvent

ExecuteStepEvent is the server-streamed response from ExecuteStep. Each event carries exactly one of the typed event payloads.

FieldTypeLabelDescription
tokenTokenEventtoken carries a single streamed token from the LLM response.
tool_callToolCallEventtool_call indicates the agent is invoking a tool.
tool_resultToolResultEventtool_result carries the output from a completed tool invocation.
statusStatusEventstatus signals an agent status transition (thinking, acting, etc.).
completionCompletionEventcompletion signals the step has finished with a final response.
metricsMetricsEventmetrics carries per-LLM-call cost and latency data.
errorErrorEventerror signals a recoverable or terminal error.
checkpointCheckpointEventcheckpoint carries a serialized LangGraph state snapshot.
securitySecurityEventsecurity signals a security violation detected by the worker.
structured_answerStructuredAnswerEventstructured_answer carries a typed answer payload (summary + table + followups) emitted when the LLM returns structured output instead of free-form text. Added in 2026-04 redesign GAP-12 (Quad chat).
step_progressStepProgressstep_progress carries the per-step progress signals the orchestrator's ProgressEval uses for stall detection in EXECUTION_MODE_AUTONOMOUS. The worker reports signals only; it never decides termination. Added in LLD-autonomous-loop-langgraph §6.1 (T4-2, #1438). Tag 11 — the oneof already occupies 1–10 (structured_answer = 10), so this MUST be 11 (no renumbering of existing arms).
interrupt_requiredInterruptRequiredinterrupt_required signals that a tool call inside the worker cycle tripped a requires_approval policy mid-step and the worker has suspended (in-step interrupt). The orchestrator routes the pending tool intent through approval.Service and resumes. Added in LLD-autonomous-loop-langgraph §6.1/§7 (T4-2, #1438). Tag 12.
decompositionDecompositionEventdecomposition carries the structured todo plan the worker produced on the PLAN step (step_goal == "decompose goal into todo plan") in EXECUTION_MODE_AUTONOMOUS. The orchestrator parses it into Plan.Todos and pursues each todo across subsequent steps. The worker reports the plan only; it never decides termination or cursor advance. An empty or absent decomposition makes the orchestrator degrade to single-todo pursuit (the empty-plan guard). Added in the T4 PLAN-result parser (T4-3 item 4 / T4-6, #1614). Tag 13 — arms 1–12 are occupied, so this MUST be 13 (no renumbering of existing arms).
write_confirmWriteConfirmEventwrite_confirm carries the structured payload of a governed write-tool confirm — the confirmation_required{approval_id, summary, deep_link, required_clearance, action_type} result a governed write tool (trigger_workflow / record_decision) returns when it stages a mutation for the user to approve in-thread. The worker detects the confirmation_required tool result and emits this ONCE per approval_id, tied to the settling turn, so the Quad client can bind an in-thread confirm card directly to the approval instead of cross-referencing ListApprovals (core#2192, kills the newest-pending-since-turn-start pairing heuristic). Tag 14 — arms 1–13 are occupied, so this MUST be 14 (no renumbering of existing arms).
input_requiredInputRequiredinput_required signals that the agent CALLED the built-in ask_user tool mid-turn (AIU-1, #2320) to elicit human input on its own judgment — NO pre-authored user_input DSL step. The worker suspended the SAME in-step interrupt path interrupt_required uses, but WITHOUT running governance (an ask_user is an elicitation, not a side-effect). It is DISTINCT from interrupt_required (arm 12) precisely so the Go side routes it to OpenUserPrompt (the durable question row + attributed live card + park), NOT to the approval-tool-gate. The orchestrator opens a user_prompt row, parks, and on the human answer resumes the turn with the answer as the ask_user tool's result (AskUserResume). Tag 15 — arms 1–14 are occupied, so this MUST be 15 (no renumbering of existing arms).

ExecuteStepRequest

ExecuteStepRequest carries the user message and session context for a single think-act-observe iteration.

FieldTypeLabelDescription
session_idstringsession_id is the UUID of the active session.
tenant_idstringtenant_id is the tenant organisation UUID (from JWT, injected by Orchestrator).
agent_idstringagent_id is the UUID of the agent configuration executing this step.
user_messagestringuser_message is the raw user input for this step.
execution_modeExecutionModeexecution_mode controls single-turn vs multi-turn behaviour.
provider_keysExecuteStepRequest.ProviderKeysEntryrepeatedprovider_keys contains decrypted BYOK keys, passed in-memory over mTLS gRPC. The worker holds these only during the LLM call and never persists them to disk or logs.
snapshotSessionSnapshotsnapshot is the immutable session configuration snapshot.
step_goalstringstep_goal is the active todo text (or "decompose goal into todo plan" for the planning step) that seeds this cycle's intent when the orchestrator drives EXECUTION_MODE_AUTONOMOUS. Empty ⇒ legacy user_message behaviour (the relay path is preserved). Added in LLD-autonomous-loop-langgraph §6.1 (T4-2, #1438); field 8 is next-free.
agent_gateway_tokenstringagent_gateway_token is a short-TTL (≈10m), agent-scoped bearer the orchestrator mints at session-init and delivers PER STEP — exactly like provider_keys (field 6): never persisted, refreshed every step, so a churned/stateless worker (#1622) always holds a fresh one. It authenticates the worker to the Go team gateway /mcp/team/{unit} AS THE AGENT: its agent_id claim is JWKS-signed and therefore unforgeable, which is what makes AuthorizeAggregated's per-agent credential + audit chain correct (a worker can never borrow a peer's id). Empty ⇒ MCP is disabled for this agent (no team gateway call is attempted). Backward-compatible: pre-MCP workers ignore an unset field. LLD #1855 PR-1 (ADR-0022). Field 9 next-free.
context_engine_tokenstringcontext_engine_token is a short-TTL (≈5m), agent-scoped bearer the orchestrator mints per step (like agent_gateway_token, field 9) and the worker attaches as Authorization: Bearer on every Context Engine call (AssembleContext / IngestEvent / ValidatePrompt). Its aud pins the Context Engine (NOT the MCP gateway) and its agent_id claim is JWKS-signed and therefore unforgeable — the CE resolves the caller's RAG scope (org/pillar/team/clearance) from a trusted DB lookup on that claim, never from the request body (#2030 Option C, founder-approved 2026-07-23). Empty ⇒ the worker falls back to unauthenticated / dev-header context calls. Never persisted; refreshed every step so a churned/stateless worker always holds a fresh one. Field 10 next-free.
prior_turnsPriorTurnrepeatedprior_turns is the bounded, role-labeled cross-turn conversation history for this session, injected by the orchestrator on the lifecycle SendMessage relay path (#2156). It is the AUTHORITATIVE cross-turn history: the worker rebuilds its working message set from prior_turns EVERY relay turn rather than relying on cross-turn in-memory carryover — the worker selector has no session affinity, so a session's turns can land on any replica and a warm in-memory history is not guaranteed. Bounded server-side (last N turns / ~M tokens, newest-kept) and EXCLUDES the current turn (read before the current user turn is captured), so it never duplicates user_message (field 4). Each entry is a final user or assistant turn — never loop-0 preambles, never tool blocks. Empty on the autonomous / temporalwf path (that path keeps its in-memory step carryover) and on a thread's first turn. Additive; pre-#2156 workers ignore it. Field 11 next-free.
ask_user_resumeAskUserResumeask_user_resume carries the ANSWER to a prior agent-initiated ask_user elicitation (AIU-1, #2320) so the worker resumes the SAME frozen turn in-context with the answer as the ask_user tool's result. It is the workflow-path analogue of the Quad-path InitWorkerSession(resume_checkpoint) seam: a WORKFLOW agent turn runs stateless single-turn (a fresh session per Temporal ExecuteAgentStep activity — cmd/agent-orchestrator/stepbridge.go), so the frozen mid-turn checkpoint cannot live worker-side across the human wait; it travels over the activity boundary (Temporal history) and returns here. When set the worker rehydrates the frozen in-step batch from checkpoint, splices answer_tool_result as a role=tool message keyed to the pending ask_user tool_call_id, and re-enters execute_tools — the skip-done logic (keyed on tool_call_id) prevents re-raising the ask. Empty on every non-ask turn ⇒ byte-for-byte today's ExecuteStep. Additive; pre-AIU workers ignore it. Field 12 next-free.

ExecuteStepRequest.ProviderKeysEntry

FieldTypeLabelDescription
keystring
valuestring

FallbackChain

FallbackChain defines the model fallback order for LLM provider resilience. If the primary model fails, the worker tries secondary, then tertiary.

FieldTypeLabelDescription
primary_modelstringprimary_model is the preferred LLM model.
secondary_modelstringsecondary_model is the first fallback if primary fails.
tertiary_modelstringtertiary_model is the second fallback if secondary also fails.

HeartbeatRequest

HeartbeatRequest is sent by the worker to signal liveness.

FieldTypeLabelDescription
session_idstringsession_id is the UUID of the active session.
worker_idstringworker_id is the unique identifier of the worker process.
active_sessionsint32active_sessions is the number of sessions this worker is handling.

HeartbeatResponse

HeartbeatResponse acknowledges the heartbeat.

FieldTypeLabelDescription
acknowledgedboolacknowledged indicates the Orchestrator received the heartbeat.

InitWorkerSessionRequest

InitWorkerSessionRequest is sent by the Orchestrator to initialize a worker with session configuration.

Resume path (delta §5.3, US-AR-6): the crash-recovery sweeper (internal/runtime/session/sweeper) reuses this RPC to rehydrate a new worker from the latest agent_checkpoints row. When resume_checkpoint is non-empty the worker MUST reload LangGraph state from those bytes instead of starting at loop_iteration=0. The blob carries the same 4-byte big-endian schema version prefix produced by internal/runtime/checkpointstore.PrependSchemaVersion; the worker strips and validates it via the Python helper shipped in #174. A version mismatch is a P1 failure and the worker MUST NOT start the session — it returns success=false with an error_message the sweeper then translates to a session_crashed audit row + reset.

FieldTypeLabelDescription
snapshotSessionSnapshotsnapshot is the immutable session configuration snapshot.
resume_checkpointbytesresume_checkpoint is the latest persisted LangGraph state blob for this session, as produced by the checkpointstore (4-byte schema version prefix + opaque body). Empty on fresh session init; populated by the sweeper on US-AR-6 reassignment. The worker uses this to restore LangGraph state before the first ExecuteStep call.
resume_loop_iterationint32resume_loop_iteration is the loop_iteration column of the agent_checkpoints row whose bytes are carried in resume_checkpoint. The worker uses it only for observability — logs/metrics/tracing — so the orchestrator-side log and the worker-side log agree on the restore point. Ignored when resume_checkpoint is empty.

InitWorkerSessionResponse

InitWorkerSessionResponse indicates whether the worker successfully initialized the session.

FieldTypeLabelDescription
successboolsuccess indicates whether initialization succeeded.
error_messagestringerror_message contains the failure reason if success is false.

InputRequired

InputRequired is the agent-initiated ask_user elicitation signal (AIU-1, #2320). It is the sibling of InterruptRequired: both suspend the worker's in-step interrupt path and freeze the mid-turn checkpoint, but an InputRequired arm carries a QUESTION for a human (not a gated tool intent for an approver) and the worker did NOT run governance on it (elicitation, not a side-effect). The orchestrator opens a durable user_prompt row from question_spec (reusing the LBE user_input machinery), parks the run, and on the answer re-drives the turn with the answer spliced as the ask_user tool result.

FieldTypeLabelDescription
tool_call_idstringtool_call_id is the identifier of the pending ask_user tool call the turn suspended on. The answer is spliced as a tool_result keyed to it on resume.
tool_namestringtool_name is the built-in tool name — always "ask_user".
idempotency_keystringidempotency_key is sha256(session_id : loop_iteration : tool_call_id) — the deterministic key that dedups a re-delivered ask across resumes/retries. It rides the durable prompt row so a re-driven turn recognises the SAME ask.
question_specbytesquestion_spec is the typed question the model asked (JSON: question, options[], allow_text, answerable_by), shaped so the Go side can persist it as the user_prompt row's prompt_spec (the same PromptSpec shape the DSL user_input node uses). Opaque bytes on the wire.
checkpointbytescheckpoint is the JSON snapshot of the frozen mid-turn state (messages incl. the ask_user tool_use, the pending current_tool_calls, and the executed-sibling tool_results). It rides the Temporal activity boundary verbatim and returns on AskUserResume.checkpoint so the worker resumes the exact frozen turn. Never carries provider keys or bearers.

InterruptRequired

InterruptRequired signals that a tool call inside the worker cycle tripped a requires_approval policy mid-step, so the worker raised interrupt() and suspended (in-step interrupt path, net-new — §7). The already-executed sibling tool_results for the in-flight cycle are persisted into the in-step checkpoint so resume skips them. The orchestrator routes pending_tool_intent through approval.Service and, on approval, resumes the cycle re-entering only the interrupted tool call.

Carried as field 12 in ExecuteStepEvent oneof (worker → orchestrator). LLD: LLD-autonomous-loop-langgraph §6.1 / §7 (T4-2, #1438).

FieldTypeLabelDescription
tool_call_idstringtool_call_id is the identifier of the gated tool call that suspended.
tool_namestringtool_name is the name of the gated tool.
idempotency_keystringidempotency_key is sha256(session_id : loop_iteration : tool_call_id) — the deterministic key the MCP proxy egress uses to dedup the gated call across resumes (§3.4 / §8.4).
pending_tool_intentbytespending_tool_intent is the structured intent for the approval payload (opaque bytes; the orchestrator forwards it to approval.Service).

McpServerRef

McpServerRef is the per-server translation entry in SessionSnapshot.mcp_servers (LLD #1855 §5). It carries only what the worker needs to reach the governed team gateway and translate the aggregated tool namespace — never a credential or an authorization decision (those live in the gateway).

FieldTypeLabelDescription
prefixstringprefix is the server's display name (mcp_servers.name) — the {prefix} segment of the aggregated {prefix}__{tool} exposed-tool namespace the team gateway advertises. Unique per org among active servers (migration 126).
unit_idstringunit_id is the org_unit whose team gateway /mcp/team/{unit_id} serves this server for this agent — the agent's home team unit (the aggregated endpoint's own unit scope). All of an agent's MCP servers are reached through this one gateway, so this is the same value for every entry in the map.

MetricsEvent

MetricsEvent carries per-LLM-call cost and latency data for observability.

FieldTypeLabelDescription
modelstringmodel is the LLM model identifier used.
input_tokensint32input_tokens is the number of prompt tokens consumed.
output_tokensint32output_tokens is the number of completion tokens generated.
cost_usddoublecost_usd is the estimated cost in US dollars.
ttft_msint32ttft_ms is the time-to-first-token latency in milliseconds.
total_msint32total_ms is the total LLM call duration in milliseconds.

PriorTurn

PriorTurn is one role-labeled turn of prior conversation history carried on ExecuteStepRequest.prior_turns (#2156). It is a compact {role, text} pair; the text is the final user or assistant text for that turn.

FieldTypeLabelDescription
rolePriorTurn.Rolerole identifies the speaker of this turn.
textstringtext is the turn's final text (never tool blocks or loop-0 preambles).

SecurityConfigProto

SecurityConfigProto is the per-tenant security pipeline configuration embedded in SessionSnapshot. The worker uses this to configure its local ToolOutputScanner and to understand the pipeline mode. LLD: #208 Section 13.

FieldTypeLabelDescription
input_filter_modestringinput_filter_mode controls input scanning: "strict", "standard", "permissive", "disabled".
output_filter_modestringoutput_filter_mode controls output scanning: "strict", "standard", "permissive", "disabled".
redact_secretsboolredact_secrets enables automatic secret redaction in LLM output.
redact_piiboolredact_pii enables automatic PII redaction in LLM output.
redact_system_promptboolredact_system_prompt enables system prompt leakage detection.
schema_validation_modestringschema_validation_mode controls schema enforcement: "log_only", "warn", "block".
tool_scan_enabledbooltool_scan_enabled enables tool output scanning in the Python worker.
tool_result_max_bytesint32tool_result_max_bytes is the maximum tool result size before truncation.
custom_block_patternsContentPatternProtorepeatedcustom_block_patterns are tenant-defined input blocking patterns.
custom_pii_patternsContentPatternProtorepeatedcustom_pii_patterns are tenant-defined PII detection patterns.

SecurityEvent

SecurityEvent signals a security violation detected by the worker or pipeline filters. Carried as field 9 in ExecuteStepEvent oneof. LLD: #208 Section 8.4.

FieldTypeLabelDescription
violation_codestringviolation_code is a machine-readable code (e.g., "input_injection_detected").
detailstringdetail is a human-readable description (NEVER returned to external clients).
severitystringseverity is the action taken: "log_only", "redact", or "block".
pattern_idstringpattern_id identifies the specific pattern that triggered the event.

SessionSnapshot

SessionSnapshot is the immutable configuration snapshot sent to the worker at session initialization. The snapshot_hash ensures config drift detection.

FieldTypeLabelDescription
session_idstringsession_id is the UUID of the session.
tenant_idstringtenant_id is the tenant organisation UUID.
agent_idstringagent_id is the agent configuration UUID.
model_idstringmodel_id is the primary LLM model identifier.
temperaturedoubletemperature is the LLM sampling temperature.
max_tokensint32max_tokens is the maximum tokens per LLM response.
toolsstringrepeatedtools is the list of tool names the agent is allowed to invoke.
guardrail_hashesstringrepeatedguardrail_hashes contains content-addressable hashes of active guardrails.
rbac_grantsSessionSnapshot.RbacGrantsEntryrepeatedrbac_grants maps resource patterns to permitted actions.
personastringpersona is the system prompt / persona text for the agent.
snapshot_hashstringsnapshot_hash is the SHA-256 hex digest of the frozen configuration.
max_loopsint32max_loops is the maximum think-act-observe iterations before forced stop.
execution_modeExecutionModeexecution_mode is the default execution mode for the session.
fallback_chainFallbackChainfallback_chain defines the model fallback order for resilience.
context_engine_addressstringcontext_engine_address is the gRPC address of the Context Engine service.
security_configSecurityConfigProtosecurity_config is the per-tenant security pipeline configuration. Added in Wave 3 (LLD #208 Section 13).
runtimestringruntime selects the worker executor: "langgraph" (default) or "claude_sdk". Empty ⇒ langgraph. Added in #1631 (ADR-0020). Part of the frozen config ⇒ included in the snapshot hash.
llm_base_urlstringllm_base_url is the Anthropic-format endpoint override for the claude_sdk runtime (ANTHROPIC_BASE_URL). Empty ⇒ SDK default. Ignored when runtime != "claude_sdk". Added in #1631 (ADR-0020).
org_version_seqint64org_version_seq is the org structure version (MAX(org_versions.version_seq)) the inheritance resolver resolved against when this snapshot was frozen. It is provenance/explainability metadata for the "why did this agent have tool X" audit view (ADR-0021 #1682, W2 review #1647 condition 5) — it records the exact org structure the frozen tool/guardrail set was derived from and is immutable for the session lifetime. It is DELIBERATELY EXCLUDED from snapshot_hash: the hash is an integrity check over the effective config, and folding a monotonic version counter into it would (a) drift every existing session's hash and (b) make otherwise-identical configs hash differently across unrelated publishes. 0 ⇒ resolver not consulted / no published version (legacy + v2.3 orgs), which serialises byte-identically to pre-#1686. Added in #1686 (T3).
mcp_serversSessionSnapshot.McpServersEntryrepeatedmcp_servers is the worker's MCP translation table: for each MCP server that SURVIVED the freeze (i.e. is present in tools[] as "mcp:<server_id>"), it maps the server_id → {prefix, unit_id}. The worker needs this to (a) pick the team gateway URL /mcp/team/{unit_id} and (b) intersect the live tools/list surface down to the {prefix}__{tool} entries this agent is allowed (the per-agent #1744 narrowing, applied worker-side).

It is DELIBERATELY EXCLUDED from snapshot_hash (like org_version_seq): the integrity-pinned effective MCP set already lives in tools[] as the "mcp:<server_id>" entries — this map is pure derived translation metadata (server display name + home team unit), never an authorization surface. Tool NAMES are NOT frozen here — they are discovered live via tools/list so the snapshot never goes stale when an upstream adds a tool. Empty for MCP-less agents, which serialise byte-identically to pre-#1855. LLD #1855 PR-1 (ADR-0022). Field 20. |

SessionSnapshot.McpServersEntry

FieldTypeLabelDescription
keystring
valueMcpServerRef

SessionSnapshot.RbacGrantsEntry

FieldTypeLabelDescription
keystring
valuestring

StatusEvent

StatusEvent signals an agent status transition.

FieldTypeLabelDescription
statusAgentStatusstatus is the new agent status.
detailstringdetail provides a human-readable description of the transition.
timestampgoogle.protobuf.Timestamptimestamp is when the status change occurred.
pending_pauseboolpending_pause is true when a pause has been requested and the session is finishing its current step before transitioning to SUSPENDED. Added in Wave 2 LLD 5.

StepProgress

StepProgress carries the per-step progress signals the orchestrator uses to detect stall in EXECUTION_MODE_AUTONOMOUS. The worker emits this at the end of each cycle (ingest_result); the orchestrator's ProgressEval derives a progress score and flags no-progress when, over the stall window, no new artifacts AND no completed todos AND a repeating response_delta_hash are observed. The worker reports signals only — it never decides termination (HLD R7, no split-brain).

Carried as field 11 in ExecuteStepEvent oneof (worker → orchestrator). LLD: LLD-autonomous-loop-langgraph §5.3 / §6.1 (T4-2, #1438).

FieldTypeLabelDescription
made_tool_callsboolmade_tool_calls is true if the worker invoked at least one tool this step.
tool_calls_erroreduint32tool_calls_errored is the count of tool invocations that returned an error.
produced_new_artifactsboolproduced_new_artifacts is true if the step yielded new output artifacts.
todo_marked_complete_by_modelbooltodo_marked_complete_by_model is true if the model signalled the active todo is done (the orchestrator re-confirms against todo state — §5.2).
response_delta_hashbytesresponse_delta_hash is a hash of the step's structured-answer sniff, used by the orchestrator's novelty signal for stall detection.

StructuredAnswerEvent

StructuredAnswerEvent is a typed answer payload emitted by the worker when the LLM returns structured output instead of free-form prose. The frontend Quad chat page (upsquad-client redesign-2026-04 quad.jsx) renders the summary + optional table + optional follow-up chips. The payload is intentionally schema-free at v1 so the frontend can evolve the renderer without forcing a proto bump every iteration; bind a schema_id when richer typing is needed (e.g., chart/card variants).

Carried as field 10 in ExecuteStepEvent oneof (worker → orchestrator) and field 7 in AgentEvent oneof (orchestrator → portal).

Sizing budgets (enforced at the orchestrator forward path so a hostile or malformed worker payload can't blow up the portal stream):

  • summary ≤ 4 KiB
  • note ≤ 2 KiB
  • columns ≤ 32 entries, each ≤ 64 bytes
  • rows ≤ 200 entries
  • cells per row ≤ 32, each ≤ 1 KiB
  • followups ≤ 8 entries, each ≤ 256 bytes Over-cap variants are dropped with a debug log; the rest of the stream keeps flowing. Limits live in internal/runtime/server/structured_answer.go.

LLD: 2026-04 redesign GAP-12 (#1099).

FieldTypeLabelDescription
summarystringsummary is the prose lede shown above the table (always present).
columnsstringrepeatedcolumns are optional column headers for table; positionally aligned with StructuredAnswerRow.cells. Empty = no header row.
rowsStructuredAnswerRowrepeatedrows is the optional tabular payload. Empty = summary-only answer.
notestringnote is an optional caption rendered below the table (e.g., "Source: AnalyticsService.GetWorkflowsBreakdown — 24h window").
followupsstringrepeatedfollowups are short suggested user follow-up prompts rendered as chips beneath the answer (e.g., "Show pending approvals").
schema_idstringschema_id is an optional opaque tag identifying a richer client-side renderer (reserved — empty in v1, where the table+summary+chips shape is the only renderer).

StructuredAnswerRow

StructuredAnswerRow is a single row in a StructuredAnswerEvent.table. Cells are positionally aligned with StructuredAnswerEvent.columns; an empty StructuredAnswerEvent.columns means cells are header-less and rendered as a free table by the client. Added in 2026-04 redesign GAP-12 (Quad chat).

FieldTypeLabelDescription
cellsstringrepeatedcells are the row's cell values, positionally aligned with the parent StructuredAnswerEvent.columns when columns is non-empty.

TerminateSessionRequest

TerminateSessionRequest asks the worker to clean up a session.

FieldTypeLabelDescription
session_idstringsession_id is the UUID of the session to terminate.
reasonstringreason describes why the session is being terminated.

TerminateSessionResponse

TerminateSessionResponse indicates whether the session was terminated.

FieldTypeLabelDescription
successboolsuccess indicates whether termination succeeded.

TodoSpec

TodoSpec is one worker-proposed sub-goal in a DecompositionEvent.

FieldTypeLabelDescription
idstringid is a worker-suggested identifier. ADVISORY only — the orchestrator overwrites it with a deterministic todo-<n> id so id authority stays orchestrator-side.
titlestringtitle is the imperative sub-goal text. Maps to the orchestrator's Todo.Text. A todo with an empty title is dropped by the orchestrator.
orderinguint32ordering is the 0-based intended position. Advisory: the orchestrator stable-sorts by it, then re-indexes ids regardless.
acceptancestringacceptance is the optional done-criteria (free text). Carried for forward-compatibility; the v1 orchestrator does not yet persist or evaluate it (T4 PLAN-result parser v1, #1614).

TokenEvent

TokenEvent carries a single streamed token from the LLM response.

FieldTypeLabelDescription
textstringtext is the token text content.
indexint32index is the token sequence number within this response.

TokenUsage

TokenUsage contains token counts and cost for a single LLM interaction.

FieldTypeLabelDescription
input_tokensint32input_tokens is the number of prompt tokens consumed.
output_tokensint32output_tokens is the number of completion tokens generated.
modelstringmodel is the LLM model identifier used.
cost_usddoublecost_usd is the estimated cost in US dollars.

ToolCallEvent

ToolCallEvent indicates the agent is invoking a tool.

FieldTypeLabelDescription
tool_namestringtool_name is the name of the tool being invoked.
tool_call_idstringtool_call_id is the unique identifier for this tool invocation.
argumentsgoogle.protobuf.Structarguments contains the tool call arguments as a JSON structure.

ToolResultEvent

ToolResultEvent carries the output from a completed tool invocation.

FieldTypeLabelDescription
tool_call_idstringtool_call_id is the identifier of the originating ToolCallEvent.
tool_namestringtool_name is the name of the tool that was invoked.
resultstringresult is the tool output as a string.
is_errorboolis_error indicates whether the tool invocation failed.
duration_msint32duration_ms is the wall-clock time of the tool execution.

WriteConfirmEvent

WriteConfirmEvent is the structured projection of a governed write-tool confirmation_required result (internal/platformmcp/write_tools.go). A governed write tool (trigger_workflow / record_decision) freezes the mutation, mints a pending approval, and returns confirmation_required{approval_id, summary, deep_link, ...} as its tool result. That result flows back to the LLM as data (the model relays the summary + link and stops), so the approval id historically never reached the client — the Quad card had to guess the pairing via ListApprovals (core#2192). This event carries the same server-authoritative fields onto the stream so the client binds the card to approval_id from the SAME turn.

The fields are all server-derived (never model-steered): summary is the clamped human summary the user authorises on; deep_link targets the approvals surface; required_clearance is the clearance tier the viewer needs to decide; action_type names the governed action (e.g. "trigger_workflow" / "record_decision"). The orchestrator re-clamps every field at the relay boundary before forwarding to the portal AgentEvent stream. Added in core#2192.

FieldTypeLabelDescription
approval_idstringapproval_id is the pending approval UUID the user must decide. Stable binding key for the in-thread confirm card + the RecordDecision call.
summarystringsummary is the server-derived, human-readable summary of the staged mutation the user authorises on. Never the raw model-typed intent.
deep_linkstringdeep_link is the relative approvals-surface link the user can open to decide out-of-thread (fallback when the in-thread card is unavailable).
required_clearanceint32required_clearance is the clearance tier (1..5) the viewer needs to decide this confirm. 0 when the write tool did not surface one.
action_typestringaction_type names the governed write action (e.g. "trigger_workflow", "record_decision") so the client can pick the right card affordances.

AgentStatus

AgentStatus represents the lifecycle state of an agent session.

NameNumberDescription
AGENT_STATUS_UNSPECIFIED0AGENT_STATUS_UNSPECIFIED is the default zero value.
AGENT_STATUS_THINKING1AGENT_STATUS_THINKING indicates the agent is processing input.
AGENT_STATUS_ACTING2AGENT_STATUS_ACTING indicates the agent is executing a tool call.
AGENT_STATUS_COMPLETE3AGENT_STATUS_COMPLETE indicates the step finished successfully.
AGENT_STATUS_ERROR4AGENT_STATUS_ERROR indicates the step ended with an error.
AGENT_STATUS_SUSPENDED5AGENT_STATUS_SUSPENDED indicates the session is paused.

Note: WAITING_APPROVAL and DELEGATING are reserved for Wave 2. |

ExecutionMode

ExecutionMode controls how the agent processes a step.

NameNumberDescription
EXECUTION_MODE_UNSPECIFIED0EXECUTION_MODE_UNSPECIFIED is the default zero value.
EXECUTION_MODE_SINGLE_TURN1EXECUTION_MODE_SINGLE_TURN processes a single chat response.
EXECUTION_MODE_MULTI_TURN2EXECUTION_MODE_MULTI_TURN processes a workflow step that may loop.
EXECUTION_MODE_AUTONOMOUS3EXECUTION_MODE_AUTONOMOUS drives the orchestrator-side deep plan loop (goal → plan → step → observe → reflect → terminate). The worker stays stateless and is driven one cycle per step; all plan state, stall detection, and termination decisions live in the Go orchestrator. Added in LLD-autonomous-loop-langgraph §6.1 (T4-2, #1438).

PriorTurn.Role

Role labels who produced the turn text.

NameNumberDescription
ROLE_UNSPECIFIED0ROLE_UNSPECIFIED is the proto3 zero value; treated as user by the worker.
ROLE_USER1ROLE_USER marks a user turn.
ROLE_ASSISTANT2ROLE_ASSISTANT marks an assistant (agent) turn.

RuntimeService

RuntimeService defines internal RPCs between the Go Orchestrator and Python Worker. It is not exposed to portal or gateway clients.

Method NameRequest TypeResponse TypeDescription
ExecuteStepExecuteStepRequestExecuteStepEvent streamExecuteStep runs the think-act-observe loop for a single user message. Returns a server-stream of ExecuteStepEvents (tokens, tool calls, status changes, metrics, and completion).
InitWorkerSessionInitWorkerSessionRequestInitWorkerSessionResponseInitWorkerSession initializes the worker with a session config snapshot. The worker uses the snapshot to configure LLM adapters, tools, and guardrails for this session.
TerminateSessionTerminateSessionRequestTerminateSessionResponseTerminateSession tells the worker to clean up and release resources associated with a session.
CheckpointCheckpointRequestCheckpointResponseCheckpoint requests the worker to serialize and return current LangGraph state for persistence and recovery.
HeartbeatHeartbeatRequestHeartbeatResponseHeartbeat is sent by the worker to signal liveness. The Orchestrator uses missed heartbeats to detect crashed workers.

Top

upsquad/runtime/v1/lifecycle.proto

AgentEvent

AgentEvent is the server-streamed response from SendMessage. It carries a subset of ExecuteStepEvent types relevant to the portal/user.

FieldTypeLabelDescription
tokenTokenEventtoken carries a single streamed token from the LLM response.
statusStatusEventstatus signals an agent status transition.
completionCompletionEventcompletion signals the step has finished with a final response.
errorErrorEventerror signals a recoverable or terminal error.
session_pausedSessionPausedEventsession_paused signals the session has transitioned to SUSPENDED. Added in Wave 2 LLD 5.
session_resumedSessionResumedEventsession_resumed signals the session has transitioned back to ACTIVE. Added in Wave 2 LLD 5.
structured_answerStructuredAnswerEventstructured_answer carries a typed answer payload (summary + table + followups) for the Quad chat renderer. Added in 2026-04 redesign GAP-12 (#1099). Defined in runtime.proto so it's reusable on the worker → orchestrator stream too.
interrupt_requiredInterruptRequiredEventinterrupt_required signals that the autonomous loop parked the session on an in-step approval gate: a tool call tripped a requires_approval policy mid-cycle. Emitted just before the accompanying SessionPaused (PAUSE_SOURCE_APPROVAL) so the dashboard can render an in-step approval banner with the gated tool + reason + approval id. The internal InterruptRequired detail (runtime.proto, worker → orchestrator) is translated into this client-safe projection with sanitized args; only governance-allowed fields are surfaced. Slice 2 dashboard wiring (#1533).
delegatedDelegatedEventEnvelopedelegated carries a LIVE event bubbled up from a delegated child sub-agent session into the PARENT (Quad) session's stream (M1 T8, #1541). It is emitted ONLY on the parent stream and ONLY for sessions that delegated (an @mention / delegate_to_agent fired). A normal, non-delegating turn never sees this arm — its stream is byte-for-byte identical to the pre-T8 behaviour. The client (#383) renders these as a nested, agent-attributed bubble inside the parent Quad thread so the user watches the sub-agent work live; the child's FINAL result still arrives via the existing delivery/resume path (no double-delivery). Tag 9.
write_confirmWriteConfirmEventwrite_confirm carries the structured payload of a governed write-tool confirm (WriteConfirmEvent, defined in runtime.proto so it is reusable on the worker → orchestrator stream too). When a governed write tool (trigger_workflow / record_decision) stages a mutation for the user to approve, the worker returns a confirmation_required{approval_id, summary, deep_link, ...} tool result. That result flows back to the LLM as data (the model relays the summary + link and stops) and historically never reached the client, forcing the Quad confirm card to guess the pairing via a ListApprovals cross-reference (core#2192). This event relays the server-authoritative payload onto the SAME turn's stream so the client binds the in-thread confirm card directly to approval_id — killing the newest-pending-since-turn-start heuristic (no clock-skew window, no org-wide newest-wins mispairing under concurrency). Every field is re-clamped at the orchestrator relay boundary before it reaches the portal. Tag 10 — arms 1–9 are occupied, so this MUST be 10 (no renumbering of existing arms). Added in core#2192.

CreateSessionRequest

CreateSessionRequest explicitly creates a new agent session.

FieldTypeLabelDescription
tenant_idstringtenant_id is the tenant organisation UUID (from JWT, injected by gateway).
user_idstringuser_id is the authenticated user UUID (from JWT).
agent_idstringagent_id is the UUID of the agent to create a session for.
execution_modeExecutionModeexecution_mode controls single-turn vs multi-turn behaviour.
model_overridestringmodel_override allows task-level model selection (AR-F66).

CreateSessionResponse

CreateSessionResponse returns metadata for the newly created session.

FieldTypeLabelDescription
session_idstringsession_id is the UUID of the created session.
snapshot_hashstringsnapshot_hash is the SHA-256 of the frozen session configuration.
statusAgentStatusstatus is the initial session status.

DelegatedEventEnvelope

DelegatedEventEnvelope wraps a single AgentEvent produced by a delegated child sub-agent session and tags it with the attribution the client needs to render a nested bubble inside the PARENT (Quad) thread (M1 T8, #1541).

Contract (the client #383 renders against THIS shape):

  • inner — the child's original AgentEvent, verbatim (token, status, tool_call/tool_result projection, completion, interrupt_required, …). The client renders inner exactly as it would a top-level event, but inside the attributed child bubble keyed by child_session_id.
  • child_session_id — the delegated child session that produced the event. Stable correlation key for grouping a child's events into one nested bubble (matches the correlation_id on the parent's SessionPaused(DELEGATION) wait marker).
  • child_agent_id — the agent running the child session (attribution: which agent is speaking). May be empty if not yet resolved.
  • subagent_invocation_id — the subagent_invocations bridge-row id linking parent ↔ child. Lets the client correlate the live bubble with the poll-based progress panel (T7's GetSubagentTree) without guessing.

Tenant isolation: a child and its parent are always the same tenant, and the envelope is published only onto the parent session's tenant-scoped stream channel (stream:{tenantID}:{parentSessionID}) — it never crosses tenants.

FieldTypeLabelDescription
innerAgentEventinner is the child's original AgentEvent, carried verbatim.
child_session_idstringchild_session_id is the delegated child session that produced inner.
child_agent_idstringchild_agent_id is the agent running the child session (attribution).
subagent_invocation_idstringsubagent_invocation_id is the parent↔child bridge-row id.

GetParentSessionRequest

GetParentSessionRequest asks for the parent of a session.

FieldTypeLabelDescription
tenant_idstringtenant_id is the tenant organisation UUID (from JWT). Optional.
session_idstringsession_id is the child UUID whose parent is being resolved.

GetParentSessionResponse

GetParentSessionResponse returns the parent link, or empty fields for a root session (NOT an error — callers should check parent.session_id).

FieldTypeLabelDescription
parentSubagentLink
is_rootboolis_root is true when the queried session is a root session (no parent). In that case parent is unset.

GetProvenanceChainRequest

GetProvenanceChainRequest requests the ancestor chain for an audit action.

FieldTypeLabelDescription
tenant_idstringtenant_id is the tenant organisation UUID (from JWT). Optional — the gateway-injected tenant always takes precedence.
session_idstringsession_id is the UUID of the session the action belongs to.
action_idstringaction_id is the UUID of the agent_audit_log row whose chain is being queried.
cross_sessionboolcross_session, when true, traverses subagent bridge boundaries so the returned chain spans the full parent↔child hierarchy up to the root user message. When false (default), the walk stops at the session boundary. Wave 3 LLD 13.

GetProvenanceChainResponse

GetProvenanceChainResponse carries the resolved provenance chain.

FieldTypeLabelDescription
session_idstringsession_id echoes the request.
action_idstringaction_id echoes the request (the chain leaf).
chainProvenanceChainLinkrepeatedchain is ordered oldest-to-newest: chain[0] is the initiating user message, chain[len-1] is the requested action itself.
truncated_at_boundarybooltruncated_at_boundary is true when a cross_session walk stopped at a boundary whose anchor failed dual-hash verification. The returned chain contains the trusted prefix; callers SHOULD alert. Wave 3 LLD 13.

GetSessionRequest

GetSessionRequest retrieves a specific session's metadata.

FieldTypeLabelDescription
tenant_idstringtenant_id is the tenant organisation UUID (from JWT).
session_idstringsession_id is the UUID of the session to retrieve.

GetSessionResponse

GetSessionResponse contains session metadata and current state.

FieldTypeLabelDescription
session_idstringsession_id is the UUID of the session.
agent_idstringagent_id is the UUID of the agent running this session.
statusAgentStatusstatus is the current session status.
loop_countint32loop_count is the number of think-act-observe iterations completed.
max_loopsint32max_loops is the configured maximum iterations.
started_atgoogle.protobuf.Timestampstarted_at is when the session was created.
last_heartbeatgoogle.protobuf.Timestamplast_heartbeat is when the worker last sent a heartbeat.
snapshot_hashstringsnapshot_hash is the SHA-256 of the session configuration.
model_idstringmodel_id is the LLM model being used for this session.

GetSubagentTreeRequest

GetSubagentTreeRequest asks for the tree rooted at session_id.

FieldTypeLabelDescription
tenant_idstringtenant_id is the tenant organisation UUID (from JWT). Optional.
session_idstringsession_id is the root of the requested tree.
max_depthint32max_depth bounds the walk. 1..10. 0 uses the default (3).

GetSubagentTreeResponse

GetSubagentTreeResponse carries the DFS-ordered tree nodes.

FieldTypeLabelDescription
nodesSubagentLinkrepeatednodes is ordered: root first, then each subtree DFS.
truncated_at_depthint32truncated_at_depth is >0 when max_depth cut the walk short; equals the max_depth actually applied.
truncated_at_fanoutbooltruncated_at_fanout is true when a node had more direct children than the per-level fan-out cap; callers should paginate with ListChildren on that node.

InterruptRequiredEvent

InterruptRequiredEvent is the portal-stream projection of an in-step approval gate (T4-7). It is emitted just before the accompanying SessionPausedEvent (PAUSE_SOURCE_APPROVAL) when the autonomous loop parks the session because a tool call tripped a requires_approval policy mid-cycle. It is the client-safe translation of the INTERNAL runtime.InterruptRequired (worker → orchestrator stream); only governance-allowed, sanitized fields are surfaced — the raw tool intent (pending_tool_intent) is NEVER forwarded to the client. The dashboard renders an in-step approval banner from these fields and uses approval_id to resolve the decision. Added for Slice 2 dashboard wiring (#1533).

FieldTypeLabelDescription
tool_namestringtool_name is the name of the gated tool whose call tripped the policy.
args_summarystringargs_summary is a sanitized, human-readable summary of the gated tool call's arguments — safe to render in the banner. Never the raw intent. Empty when no governance-safe summary is available.
reasonstringreason is the human-readable reason the call was gated (the tripped policy / clearance requirement). Empty when no specific reason is known beyond "requires approval".
approval_idstringapproval_id is the pending approval the operator must decide. The dashboard resolves the in-step gate against this id.
tool_call_idstringtool_call_id is the identifier of the gated tool call within the worker cycle (correlation with audit + resume).

ListChildrenRequest

ListChildrenRequest asks for direct children of session_id (one level).

FieldTypeLabelDescription
tenant_idstringtenant_id is the tenant organisation UUID (from JWT). Optional.
session_idstringsession_id is the parent UUID; children of this session are returned.
page_sizeint32page_size bounds the response. 1..100. 0 uses the default (20).
page_tokenstringpage_token is the cursor for the next page.

ListChildrenResponse

ListChildrenResponse returns paginated direct children.

FieldTypeLabelDescription
childrenSubagentLinkrepeated
next_page_tokenstringnext_page_token is empty when no further pages remain.
total_countint32total_count is the number of direct children (may be larger than len(children) under pagination).

ListSessionsRequest

ListSessionsRequest queries sessions with optional filters and pagination.

FieldTypeLabelDescription
tenant_idstringtenant_id is the tenant organisation UUID (from JWT).
agent_idstringagent_id optionally filters sessions by agent.
status_filterstringstatus_filter optionally filters sessions by status.
page_sizeint32page_size is the maximum number of sessions to return. Max 100.
page_tokenstringpage_token is the cursor for the next page of results.

ListSessionsResponse

ListSessionsResponse contains a paginated list of sessions.

FieldTypeLabelDescription
sessionsGetSessionResponserepeatedsessions is the list of session metadata entries.
next_page_tokenstringnext_page_token is the cursor for the next page. Empty if no more pages.
total_countint32total_count is the total number of sessions matching the filters.

PauseSessionRequest

PauseSessionRequest asks to suspend an active session. The pause commits only at the next message boundary (never mid-tool or mid-LLM).

FieldTypeLabelDescription
tenant_idstringtenant_id is the tenant organisation UUID (from JWT, injected by gateway).
session_idstringsession_id is the UUID of the session to pause.
reasonstringreason is a human-readable explanation recorded in audit trail.
pause_sourcePauseSourcepause_source identifies who initiated the pause.
correlation_idstringcorrelation_id is optional — set to approval_id when pause_source=APPROVAL.

PauseSessionResponse

PauseSessionResponse returns the post-pause session state.

FieldTypeLabelDescription
statusAgentStatusstatus is the session status after pause (SUSPENDED on success).
checkpoint_keystringcheckpoint_key is the key of the checkpoint persisted at pause commit.
paused_atgoogle.protobuf.Timestamppaused_at is the timestamp the session transitioned to SUSPENDED.
was_already_suspendedboolwas_already_suspended is true when the session was already SUSPENDED at RPC entry; idempotent double-pause returns OK with this flag set.

ProvenanceChainLink is one entry in a provenance chain, ordered from root (initiating user message) to leaf (the requested action).

FieldTypeLabelDescription
action_idstringaction_id is the UUID of the agent_audit_log row for this link.
action_typestringaction_type is the audit_action_type enum value (e.g. "message_received").
agent_idstringagent_id is the agent that produced this action, when applicable.
created_atgoogle.protobuf.Timestampcreated_at is the timestamp of the link, RFC3339 in UTC.
parent_action_idstringparent_action_id is the action_id of the parent link in the same session. Empty on root actions (session_started, message_received).
schema_versionstringschema_version identifies the chain link schema revision for forward-compatible evolution. Currently "1".
session_idstringsession_id is the session the link's audit row lives in. Identical across all links of a same-session walk; differs across a cross_session walk's subagent boundary crossings. Wave 3 LLD 13.
is_boundary_crossingboolis_boundary_crossing is true when the previous link lived in a different session (subagent bridge boundary). Wave 3 LLD 13.
anchor_verifiedboolanchor_verified is true when the bridge row's dual-hash anchor verification succeeded at the boundary crossing. When false, the link is the last trusted link before the boundary; subsequent links returned are provided for observability but MUST be treated as untrusted. Wave 3 LLD 13.

ResumeSessionRequest

ResumeSessionRequest asks to resume a suspended session.

FieldTypeLabelDescription
tenant_idstringtenant_id is the tenant organisation UUID (from JWT, injected by gateway).
session_idstringsession_id is the UUID of the session to resume.
operator_inputbytesoperator_input is optional JSON injected as a system-tagged context message on resume. Bounded at 64 KiB; larger payloads are rejected with InvalidArgument.
resume_reasonstringresume_reason is a human-readable explanation recorded in audit trail.

ResumeSessionResponse

ResumeSessionResponse returns the post-resume session state.

FieldTypeLabelDescription
statusAgentStatusstatus is the session status after resume (ACTIVE on success).
resumed_at_loopint32resumed_at_loop is the loop_iteration read from the latest checkpoint.
resumed_atgoogle.protobuf.Timestampresumed_at is the timestamp the session transitioned back to ACTIVE.

SendMessageRequest

SendMessageRequest carries a user message to an agent session.

FieldTypeLabelDescription
tenant_idstringtenant_id is the tenant organisation UUID (from JWT, injected by gateway).
user_idstringuser_id is the authenticated user UUID (from JWT).
agent_idstringagent_id is the UUID of the agent to send the message to.
session_idstringsession_id is the UUID of an existing session. Empty means create new.
messagestringmessage is the user's input text.
execution_modeExecutionModeexecution_mode controls single-turn vs multi-turn behaviour.

SessionPausedEvent

SessionPausedEvent is emitted on the portal stream when a session transitions to SUSPENDED. After this event the stream stays open with keepalive pings until a SessionResumedEvent or TerminateSession.

FieldTypeLabelDescription
reasonstringreason is the human-readable reason recorded on the pause RPC.
pause_sourcePauseSourcepause_source identifies who initiated the pause.
correlation_idstringcorrelation_id echoes PauseSessionRequest.correlation_id.
checkpoint_keystringcheckpoint_key is the key of the checkpoint persisted at pause commit.
paused_atgoogle.protobuf.Timestamppaused_at is the timestamp of the transition.

SessionResumedEvent

SessionResumedEvent is emitted on the portal stream when a session transitions from SUSPENDED back to ACTIVE.

FieldTypeLabelDescription
resumed_by_approvalboolresumed_by_approval is true when the resume was triggered from the approval engine (LLD 6); false for operator-initiated resume.
approval_idstringapproval_id is populated when resumed_by_approval=true.
resumed_at_loopint32resumed_at_loop is the loop_iteration the worker restored from.
resumed_atgoogle.protobuf.Timestampresumed_at is the timestamp of the transition.

SubagentLink is one node in a delegation tree. Fields mirror the agent_sessions row + the join against subagent_invocations for the bridge metadata (role, status, result summary).

FieldTypeLabelDescription
session_idstringsession_id is the UUID of the child session.
parent_session_idstringparent_session_id is the UUID of the parent session. Empty on the root of a tree.
root_session_idstringroot_session_id is the UUID of the tree root.
delegation_depthint32delegation_depth is 0 on the root, 1+ for descendants.
agent_idstringagent_id is the UUID of the agent running this child session.
subagent_rolestringsubagent_role is the symbolic role (e.g. "research"). Empty on the root session.
subagent_invocation_idstringsubagent_invocation_id is the bridge row primary key. Empty on the root session.
statusstringstatus is the session status (active, suspended, terminated, error, crashed, initializing).
started_atgoogle.protobuf.Timestampstarted_at is when this child session was created.
ended_atgoogle.protobuf.Timestampended_at is when this child session transitioned to terminal (null on live sessions).
result_statusstringresult_status is the bridge row's status (pending, ok, error, timeout, cancelled). Empty on the root session.
result_error_codestringresult_error_code echoes subagent_invocations.error_code when the result_status is not ok; empty otherwise.

TerminateLifecycleSessionRequest

TerminateLifecycleSessionRequest asks to end an active session. Named differently from runtime.TerminateSessionRequest to avoid proto name collision within the same package.

FieldTypeLabelDescription
tenant_idstringtenant_id is the tenant organisation UUID (from JWT).
session_idstringsession_id is the UUID of the session to terminate.
reasonstringreason describes why the session is being terminated.

TerminateLifecycleSessionResponse

TerminateLifecycleSessionResponse confirms session termination.

FieldTypeLabelDescription
successboolsuccess indicates whether termination succeeded.
statusAgentStatusstatus is the final session status after termination.

TerminateSubagentTreeRequest

TerminateSubagentTreeRequest requests cascade termination of a subtree.

FieldTypeLabelDescription
tenant_idstringtenant_id is the tenant organisation UUID (from JWT). Optional.
session_idstringsession_id is the root of the subtree to terminate.
reasonstringreason is a human-readable explanation recorded on every terminated session's audit trail.
include_rootboolinclude_root, when true, terminates session_id itself in addition to its descendants. When false, only descendants are terminated.

TerminateSubagentTreeResponse

TerminateSubagentTreeResponse reports the cascade outcome.

FieldTypeLabelDescription
terminated_session_idsstringrepeatedterminated_session_ids lists every session flipped to terminated by this call.
skipped_session_idsstringrepeatedskipped_session_ids lists sessions already in a terminal state.
updated_bridge_row_countint32updated_bridge_row_count counts subagent_invocations rows flipped to cancelled as part of the cascade.

PauseSource

PauseSource identifies who initiated a pause. APPROVAL and POLICY are reserved for LLD 6 (approval engine) and future policy-driven pauses. DELEGATION and DELEGATION_APPROVAL were added in Wave 3 LLD 10 for parent-awaits-child and parent-awaits-approval-to-spawn-child flows.

NameNumberDescription
PAUSE_SOURCE_UNSPECIFIED0PAUSE_SOURCE_UNSPECIFIED is the default zero value.
PAUSE_SOURCE_OPERATOR1PAUSE_SOURCE_OPERATOR is a human-operator-initiated pause.
PAUSE_SOURCE_APPROVAL2PAUSE_SOURCE_APPROVAL is an approval-engine-initiated pause (LLD 6).
PAUSE_SOURCE_POLICY3PAUSE_SOURCE_POLICY is a policy-driven pause (reserved).
PAUSE_SOURCE_DELEGATION4PAUSE_SOURCE_DELEGATION — parent session awaiting a child subagent to return a result (Wave 3 LLD 10/12/13).
PAUSE_SOURCE_DELEGATION_APPROVAL5PAUSE_SOURCE_DELEGATION_APPROVAL — parent awaiting approval to spawn a child subagent (Wave 3 LLD 14).

LifecycleService

LifecycleService defines portal-facing RPCs for session management and user messaging. The WebSocket Gateway calls these on behalf of users.

Method NameRequest TypeResponse TypeDescription
SendMessageSendMessageRequestAgentEvent streamSendMessage sends a user message and returns a stream of AgentEvents. Called by the WebSocket Gateway on behalf of the user. If session_id is empty, a new session is created automatically.
CreateSessionCreateSessionRequestCreateSessionResponseCreateSession explicitly creates a new agent session without sending a message. Useful for pre-warming or explicit session management.
GetSessionGetSessionRequestGetSessionResponseGetSession retrieves the current state and metadata of a session.
ListSessionsListSessionsRequestListSessionsResponseListSessions returns paginated sessions for an agent or tenant.
TerminateSessionTerminateLifecycleSessionRequestTerminateLifecycleSessionResponseTerminateSession ends an active session and releases its resources.
GetProvenanceChainGetProvenanceChainRequestGetProvenanceChainResponseGetProvenanceChain returns the full ancestor chain for an audit action, walking from the requested action back to the initiating user message. Implements US-AR-10 read surface (Wave 2 delta §7).
PauseSessionPauseSessionRequestPauseSessionResponsePauseSession transitions an ACTIVE session to SUSPENDED at the next clean message boundary. Idempotent: pausing an already-SUSPENDED session returns OK with was_already_suspended=true. LLD: Wave 2 LLD 5.
ResumeSessionResumeSessionRequestResumeSessionResponseResumeSession re-hydrates a SUSPENDED session from its latest checkpoint, optionally injecting operator_input as a system-tagged context message. Returns FailedPrecondition on non-SUSPENDED sessions. LLD: Wave 2 LLD 5.
ListChildrenListChildrenRequestListChildrenResponseListChildren returns the direct children of a session (one level deep). Paginated for wide fan-out trees. Tenant-scoped (RLS). Added in Wave 3 LLD 13.
GetParentSessionGetParentSessionRequestGetParentSessionResponseGetParentSession returns the parent of a session. Returns an empty parent (not an error) for root sessions. Tenant-scoped (RLS). Added in Wave 3 LLD 13.
GetSubagentTreeGetSubagentTreeRequestGetSubagentTreeResponseGetSubagentTree returns the DFS-ordered delegation tree rooted at a session. Truncated at max_depth to bound response size; callers can paginate by repeatedly calling with the returned subtree IDs. Tenant-scoped (RLS). Added in Wave 3 LLD 13.
TerminateSubagentTreeTerminateSubagentTreeRequestTerminateSubagentTreeResponseTerminateSubagentTree cascades a TerminateSession across a session and every descendant. Operator-triggered; tenant-scoped. Added in Wave 3 LLD 13.

Top

upsquad/runtime/v1/model.proto

CapabilityProfile

CapabilityProfile scores a model across key dimensions (0.0-1.0 each). Used by the recommendation engine to match models to agent roles.

FieldTypeLabelDescription
reasoningdoublereasoning is the model's reasoning and analysis capability score.
code_generationdoublecode_generation is the model's code generation capability score.
structured_opsdoublestructured_ops is the model's structured output capability score.
long_contextdoublelong_context is the model's long context handling capability score.
cost_efficiencydoublecost_efficiency is the model's cost-to-quality ratio score.

CompareModelsRequest

CompareModelsRequest asks for side-by-side model comparison data.

FieldTypeLabelDescription
model_idsstringrepeatedmodel_ids is the list of model identifiers to compare.

CompareModelsResponse

CompareModelsResponse contains the compared model entries.

FieldTypeLabelDescription
modelsModelEntryrepeatedmodels contains the full model entries for each requested model.

GetModelRecommendationRequest

GetModelRecommendationRequest asks the recommendation engine for the best model given a role, connected providers, and optimization goal.

FieldTypeLabelDescription
agent_rolestringagent_role is the agent's functional role (e.g., "architect", "backend-sme", "qa-engineer").
connected_providersstringrepeatedconnected_providers lists the providers the tenant has BYOK keys for.
optimization_goalstringoptimization_goal is the optimization preference: "quality", "cost", or "balanced".

GetModelRecommendationResponse

GetModelRecommendationResponse contains the recommended model and alternatives with reasoning.

FieldTypeLabelDescription
recommendedModelEntryrecommended is the top recommended model for the given criteria.
alternativesModelEntryrepeatedalternatives are other suitable models ranked by fit.
reasoningstringreasoning explains why the recommended model was chosen.

ListModelsRequest

ListModelsRequest queries the model catalogue.

FieldTypeLabelDescription
provider_filterstringprovider_filter optionally restricts results to a single provider.

ListModelsResponse

ListModelsResponse contains the list of models matching the filter.

FieldTypeLabelDescription
modelsModelEntryrepeatedmodels is the list of model catalogue entries.

ModelEntry

ModelEntry describes a single LLM model in the catalogue.

FieldTypeLabelDescription
model_idstringmodel_id is the canonical model identifier (e.g., "claude-sonnet-4-20250514").
providerstringprovider is the LLM provider name ("anthropic", "openai", "google").
display_namestringdisplay_name is the human-readable model name for UI display.
capabilitiesCapabilityProfilecapabilities contains the model's capability profile scores.
pricingModelPricingpricing contains the per-token cost data.
max_context_tokensint32max_context_tokens is the maximum context window size in tokens.
supports_streamingboolsupports_streaming indicates whether the model supports token streaming.
supports_tool_useboolsupports_tool_use indicates whether the model supports tool/function calling.
tool_use_quality_scoredoubletool_use_quality_score is a 0.0-1.0 rating of tool-use reliability.
is_deprecatedboolis_deprecated indicates the model is scheduled for removal.

ModelPricing

ModelPricing contains per-token cost data for a model.

FieldTypeLabelDescription
input_per_million_tokensdoubleinput_per_million_tokens is the cost in USD per million input tokens.
output_per_million_tokensdoubleoutput_per_million_tokens is the cost in USD per million output tokens.

ModelRegistryService

ModelRegistryService provides a curated model catalogue with capability profiles, pricing data, and role-based model recommendations.

Method NameRequest TypeResponse TypeDescription
ListModelsListModelsRequestListModelsResponseListModels returns the full model catalogue, optionally filtered by provider.
GetModelRecommendationGetModelRecommendationRequestGetModelRecommendationResponseGetModelRecommendation returns the best model for a given agent role and optimization goal, considering which providers the tenant has connected via BYOK.
CompareModelsCompareModelsRequestCompareModelsResponseCompareModels returns side-by-side capability and pricing data for a set of models. Used by the portal comparison UI.

Scalar Value Types

.proto TypeNotesC++JavaPythonGoC#PHPRuby
doubledoubledoublefloatfloat64doublefloatFloat
floatfloatfloatfloatfloat32floatfloatFloat
int32Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead.int32intintint32intintegerBignum or Fixnum (as required)
int64Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead.int64longint/longint64longinteger/stringBignum
uint32Uses variable-length encoding.uint32intint/longuint32uintintegerBignum or Fixnum (as required)
uint64Uses variable-length encoding.uint64longint/longuint64ulonginteger/stringBignum or Fixnum (as required)
sint32Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s.int32intintint32intintegerBignum or Fixnum (as required)
sint64Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s.int64longint/longint64longinteger/stringBignum
fixed32Always four bytes. More efficient than uint32 if values are often greater than 2^28.uint32intintuint32uintintegerBignum or Fixnum (as required)
fixed64Always eight bytes. More efficient than uint64 if values are often greater than 2^56.uint64longint/longuint64ulonginteger/stringBignum
sfixed32Always four bytes.int32intintint32intintegerBignum or Fixnum (as required)
sfixed64Always eight bytes.int64longint/longint64longinteger/stringBignum
boolboolbooleanbooleanboolboolbooleanTrueClass/FalseClass
stringA string must always contain UTF-8 encoded or 7-bit ASCII text.stringStringstr/unicodestringstringstringString (UTF-8)
bytesMay contain any arbitrary sequence of bytes.stringByteStringstr[]byteByteStringstringString (ASCII-8BIT)