Kernel API Reference (L0)
The substrate.kernel package defines the immutable domain contracts, routing addresses, and messaging units that form the foundation of the agent substrate.
Identity & Routing (substrate.kernel.core.identity)
Actor
Pure routing address representing an actor instance. An Actor is stateless and holds no runtime objects—it is a pure coordinate type/key used by routers, mailboxes, and supervisors.
from substrate.kernel.core.identity import Actor
# Keyed instance (e.g. conversational agent)
agent = Actor(type="conversation", key="conv_01j8a")
assert str(agent) == "conversation/conv_01j8a"
assert not agent.is_singleton
# Singleton actor (no instance key)
gateway = Actor(type="http_proxy")
assert str(gateway) == "http_proxy"
assert gateway.is_singleton
# Parse from string
restored = Actor.from_str("conversation/conv_01j8a")
assert restored == agentCanonical Factory Methods
To prevent string typos and enforce uniform provenance across the platform:
Actor.system(key="bootstrap")— Address for internal runtime, cron, and maintenance operations ("system/bootstrap").Actor.user(key="default")— Address for human user ingress ("user/default"or"user/<user_id>").Actor.generate(type)— Generates an ephemeral actor with a unique UUID4 key.
Topic
Flat pub/sub channel address for fan-out messaging across the FollowGraph.
from substrate.kernel.core.identity import Topic
# Named broadcast channel
channel = Topic("market.crypto.prices")
# Standard runtime channels
progress_topic = Topic.progress(run_id="run_4910b8")
assert str(progress_topic) == "agent.progress/run_4910b8"
stream_topic = Topic.stream(run_id="run_4910b8")
assert str(stream_topic) == "agent.stream/run_4910b8"Messaging (substrate.kernel.messaging.message)
Message
The fundamental unit of agent-to-agent and ingress communication. Every message requires both a destination (target) and an origin (sender).
from substrate.kernel.core.identity import Actor
from substrate.kernel.core.content import ChatMessage, Role, TextBlock
from substrate.kernel.messaging.message import Message, ChatPayload
msg = Message(
target=Actor(type="agent", key="analyst"),
sender=Actor.user("usr_4910"),
payload=ChatPayload(
message=ChatMessage(
role=Role.USER,
content=[TextBlock(text="Summarize the latest report")]
)
),
correlation_id="thread_9910a",
metadata={"tenant_id": "tenant_enterprise_1"}
)Why Senders Are Strictly Mandatory
In enterprise distributed systems, anonymous messages are a critical liability. Message.sender: Actor is enforced at the kernel boundary:
- Per-Sender FIFO Guarantees: Mailboxes (
Inbox) order and drain messages per-sender. Anonymous messages would collapse into a shared queue and cause cross-client head-of-line blocking. - Zero-Trust Auditing & Security: Every message preserves verifiable provenance for SOC2, HIPAA, and tenant isolation policies.
- Causality & Observability: Distributed tracing spans map direct links between
senderandtargetwithout severed roots. - Asynchronous Replies: Recipients can reliably send back receipts, error reports, and responses (
ctx.reply()).
Polymorphic Payloads
All payloads subclass PayloadBase and round-trip cleanly across JSON transports:
ChatPayload— Conversation turns containing aChatMessage.DataPayload— Arbitrary JSON-serializable structured data dictionaries.ToolCallRequest— Request to invoke a tool with arguments.ToolExecutionResult— Output or error resulting from tool execution.
Token Usage Contract (substrate.kernel.core.usage)
Usage
Immutable value object tracking token consumption across models and providers.
from substrate.kernel.core.usage import Usage
step_1 = Usage(input_tokens=100, cached_tokens=40, output_tokens=50, reasoning_tokens=20)
step_2 = Usage(input_tokens=80, cached_tokens=60, output_tokens=40, reasoning_tokens=10)
# Monoidal aggregation across steps and subagents
total = step_1 + step_2
assert total.input_tokens == 180
assert total.cached_tokens == 100
assert total.total_tokens == 270cached_tokens: Tokens served from provider prompt cache (Anthropic prompt caching, OpenAI cached tokens).reasoning_tokens: Chain-of-thought / extended thinking tokens (OpenAI o-series, Claude thinking).
Content Blocks (substrate.kernel.core.content)
Standard multimodal container models:
TextBlock— Plain text strings.ImageBlock— Binary image data, MIME type, and optional URLs.ToolUseBlock— Tool call invocation (call ID, tool name, parsed arguments).ToolResultBlock— Tool execution output or error text.ReasoningBlock— Chain-of-thought tokens (redacted or raw).DataBlock— Arbitrary structured payload blocks.UnknownBlock— Preserves unmodeled future provider block schemas without data loss.
from substrate.kernel.core.content import ChatMessage, Role, TextBlock, ToolUseBlock
assistant_turn = ChatMessage(
role=Role.ASSISTANT,
content=[
TextBlock(text="Checking stock availability..."),
ToolUseBlock(call_id="call_01", tool_name="check_inventory", arguments={"sku": "A123"})
]
)