Skip to main content

Slot Context SDK

Agent Slots receive a ctx object from the host. The object depends on the slot phase. Bootstrap slots run before a turn exists, so they receive only session-level context. Input and output slots run inside a turn, so they receive the turn, history, state, tools, and child-agent clients.

Context Availability

AttributeBootstrapInputOutputMeaning
ctx.session_idYesVia ctx.turnVia ctx.turnCurrent session id.
ctx.core_idYesVia ctx.turnVia ctx.turnActive Agent Core id.
ctx.core_revisionYesVia ctx.turnVia ctx.turnActive Agent Core Git revision.
ctx.workspaceYesVia ctx.input.workspaceVia ctx.output.workspaceResolved workspace root.
ctx.turnNoYesYesTurn metadata.
ctx.slot_idYesYesYesDirectory name for the current slot.
ctx.slot_pathYesYesYesCore-relative slot path, such as agent/input/style_hint.
ctx.capabilityYesYesYesCapability facade with can(...) and require(...).
ctx.bootstrapYesNoNoBootstrap context writer.
ctx.inputNoYesNoCurrent-turn input builder and input delivery client.
ctx.outputNoNoYesProvider response delivery client.
ctx.historyNoYesYesCurrent-session history reader.
ctx.stateNoYesYesHost-managed core/session state client.
ctx.toolsNoYesYesHost tool-call client.
ctx.agentsNoYesYesChild-agent run/spawn client.
ctx.skillsNoYesNoSkill activation client.
ctx.resultNoNoYesStructured result writer for the current turn.

Bootstrap slots do not receive ctx.history, ctx.state, ctx.tools, ctx.agents, ctx.skills, or ctx.result.

Turn Metadata

Input and output slots can read ctx.turn:

FieldTypeMeaning
session_idstrCurrent session id.
turn_idstrCurrent turn id.
core_idstrActive Agent Core id.
core_revisionstrCurrent live Agent Core revision.
user_input.contentstrRaw inbound text for the turn.
user_input.metadatadictHost/channel metadata attached to the inbound.
metadatadictTurn metadata from the runtime.

Bootstrap Client

Bootstrap slots add session-stable context:

def process(ctx):
ctx.bootstrap.add("Remember that this session is about release prep.")
MethodMeaning
ctx.bootstrap.add(text)Adds non-empty text to the bootstrap snapshot.

Bootstrap return values are ignored. Store all bootstrap text through ctx.bootstrap.add(...). Slot return values are not interpreted as host effect requests; use the documented ctx.input, ctx.output, ctx.state, ctx.tools, ctx.agents, and ctx.result clients instead.

Input Client

Input slots shape the current turn before the provider call.

Attribute or methodMeaning
ctx.input.raw_textRaw inbound text.
ctx.input.attachmentsTuple of inbound attachment metadata.
ctx.input.workspaceResolved workspace root as a Path.
ctx.input.session_rootSession artifact root as a Path.
ctx.input.add_context(content, role="system", write_history=None)Add system or user text to the current prompt.
ctx.input.add(section, content, history_policy=None)Lower-level prompt add; section must be system or user.

add_context(..., role="system") defaults to transient input context. add_context(..., role="user") defaults to persisted user history.

The seed base_input slot appends ctx.input.raw_text as the user message. Custom input slots that add hints normally run before base_input.

Parallel input slots cannot modify the current prompt. Calling ctx.input.add_context(...) or ctx.input.add(...) from a parallel input slot raises RuntimeError.

Output Client

Output slots handle the provider response after the model/tool loop.

Attribute or methodMeaning
ctx.output.response_textFinal provider response text.
ctx.output.contentSame text as response_text.
ctx.output.metadataTurn interaction metadata.
ctx.output.workspaceResolved workspace root as a Path.
ctx.output.session_rootSession artifact root as a Path.

The seed base_output slot delivers ctx.output.response_text. If a pipeline omits base_output, another output slot must deliver or record the response.

Delivery Methods

Input and output clients expose the same delivery methods. Input deliveries default to transient history because input slots run before the assistant response. Output deliveries default from the slot's history_policy.

send_text

ctx.output.send_text(
text,
write_history=None,
history_policy=None,
visible=True,
history_text=None,
failure_history_text=None,
delivery_metadata=None,
)
ParameterMeaning
textText block to deliver.
write_historyTrue maps to persist; False maps to transient unless history_policy is set.
history_policyOne of persist, model_hidden, or transient.
visibleWhether the delivery is user-visible.
history_textText written to history; defaults to text.
failure_history_textText available for failure history handling.
delivery_metadataExtra metadata attached to the delivery request.

send_image, send_audio, send_video, send_file

ctx.output.send_file(
source,
caption=None,
media_type=None,
summary=None,
artifact_metadata=None,
write_history=None,
history_policy=None,
visible=True,
history_text=None,
failure_history_text=None,
delivery_metadata=None,
)

The artifact helpers share the same parameters:

ParameterMeaning
sourceWorkspace/session path, URL, or ArtifactRef.
captionText shown with the artifact block.
media_typeMIME type hint.
summaryArtifact summary stored by the host.
artifact_metadataMetadata stored with the artifact.
write_history, history_policy, visible, history_text, failure_history_text, delivery_metadataSame history and delivery controls as send_text.

Local artifact paths must be inside ctx.input.workspace, ctx.output.workspace, or the matching session_root. Artifact deliveries that write history should provide history_text; otherwise later model context has no usable text representation.

progress and notice

ctx.output.progress("Still working...")
ctx.output.notice("Skipped optional indexing step.")
MethodMeaning
progress(text, visible=True, delivery_metadata=None)Emit transient progress.
notice(text, visible=True, delivery_metadata=None)Emit a transient notice.

progress and notice always use transient history. They do not accept history_policy.

History Client

Input and output slots can inspect current-session history:

messages = ctx.history.recent_messages(5, roles={"user", "assistant"})
for message in messages:
ctx.output.notice(f"{message.role}: {message.content[:80]}")
APIMeaning
ctx.history.recent_messages(limit, roles=None)Return recent HistoryMessageSummary items from the current session.

roles defaults to {"user", "assistant", "tool"}. Other roles are ignored. A non-positive limit returns an empty list.

HistoryMessageSummary has:

FieldMeaning
message_idSession message id.
roleuser, assistant, or tool.
contentStored message text.
turn_idTurn that produced the message, when known.
created_atCreation timestamp string.
step_idModel/tool-loop step id, when available.
tool_call_idTool call id for tool result messages.
tool_callsAssistant tool calls attached to assistant messages.
visibleWhether the message is user-visible.
model_visibleWhether later provider context can include the message.
tool_nameTool name for tool result messages.
is_errorTool error flag for tool result messages.

State Client

Input and output slots can use host-managed state:

count = ctx.state.session.get("draft_count", 0)
ctx.state.session.set("draft_count", count + 1)
ctx.state.core.merge("preferences", {"tone": "concise"})

ctx.state.core is scoped to the Agent Core. ctx.state.session is scoped to the current session.

MethodRequired capabilityMeaning
get(target, default=None)state.core.read or state.session.readRead one target.
set(target, value)state.core.write or state.session.writeReplace one target.
merge(target, value)Write capabilityMerge an object into one target.
append(target, value)Write capabilityAppend one value to a target.
snapshot()Read capabilityReturn the full state snapshot for that scope.

Target-specific grants such as state.session.write:draft_count can satisfy a targeted operation when configured. Otherwise the generic scope capability is required.

Each set, merge, or append call is serialized with other writes to the same state file inside one host process and commits the state snapshot together with its proposal-audit record. The host uses atomic files and recovers an interrupted commit on the next state read. POSIX state directories/files are restricted to 0700/0600; Windows uses platform ACL semantics. This is not an inter-process transaction boundary: multiple host processes must not share one runtime home. Also, a separate get() followed by set() is not one atomic read-modify-write operation; the planned transactional StateRuntime will own that stronger contract.

Tools Client

Input and output slots can call visible tools:

result = await ctx.tools.call("project_note", {"topic": "release"})
ctx.output.notice(result.content)
APIRequired capabilityMeaning
await ctx.tools.call(name, arguments=None)tool.call:<name>Execute a visible host, authored, or MCP tool.

The tool must be visible to the current core and allowed by normal host capability and approval policy.

Child Agent Client

Input and output slots can run child agents:

result = await ctx.agents.run(
"assistant",
"Summarize this for the parent slot.",
input_slots=["base_input"],
output_slots=["base_output"],
tools="none",
)

handle = ctx.agents.spawn(
"assistant",
"Review this later.",
input_slots="all",
output_slots="all",
tools=["tools_list"],
use_bootstrap=True,
)
APIRequired capabilityMeaning
await ctx.agents.run(core_id, raw_input, ...)agents.run:<core_id>Run a child turn and wait for AgentRunResult.
ctx.agents.spawn(core_id, raw_input, ...)agents.spawn:<core_id>Start an agent.spawn background task and return AgentSpawnHandle.

Both calls accept:

ParameterMeaning
contextExtra string or list of strings injected into the child turn.
input_slotsNone, [], "all", or a non-empty list of child input slot ids.
output_slotsNone, [], "all", or a non-empty list of child output slot ids.
use_bootstrapDefaults to False; True uses the child core bootstrap pipeline.
tools"all", "none", [], or a list of child tool ids.

For input_slots and output_slots, omitted, None, or [] runs only base_input or base_output. "all" runs the child core's full configured pipeline. A non-empty list filters the active child pipeline by slot id.

For tools, omitted, None, or "all" uses the child core's configured tools. "none" or [] hides all child tools. A non-empty list narrows the child core's configured tools.

Skills Client

Input slots can activate skills for the current turn:

def process(ctx):
ctx.skills.activate("release-checklist")

The slot needs skill.activate or skill.activate:<skill> capability. Unknown skill names are ignored after the activation request is recorded.

Result Client

Output slots can set a structured result for the current turn:

def process(ctx):
ctx.result.set({"summary": ctx.output.response_text[:200]})
APIMeaning
ctx.result.valueCurrent result value, or None if unset.
ctx.result.set(value)Set or merge a JSON-compatible result value.

Parallel output slots cannot modify ctx.result. Result values must be JSON-compatible. Floating point values must be finite.

Capability Checks

Use ctx.capability when authored code is about to request a host-mediated effect:

def process(ctx):
ctx.capability.require("fs.read", slot_path=ctx.slot_path)
APIMeaning
ctx.capability.can(capability, slot_path=ctx.slot_path)Return whether the capability is granted.
ctx.capability.require(capability, slot_path=ctx.slot_path)Raise if the capability is not granted.

Declaring a capability in slot.yaml makes the grant available to the slot. It does not bypass host approval, workspace scope, command guards, channel policy, or tool runtime rules.