core/ — The Universal Primitives¶
Source:
kernel/core/content.py·kernel/core/identity.py·kernel/core/usage.py·kernel/core/errors.py
Every agent message, every tool result, and every event payload in the entire system is built from these four files. Nothing in the kernel imports from outside core/ except within core/ itself.
ContentBlock — The Universal Payload Primitive¶
Every list of data passed between agents, to the LLM, and back from tools is a list[ContentBlock]. There is no other payload type. The type literal field is the discriminator — Pydantic routes deserialization automatically.
| Category | Block Type | Discriminator (type) | Core Fields | Description |
|---|---|---|---|---|
| Text & Data | TextBlock | 'text' | text: str | Plain text message contents. |
CodeBlock | 'code' | code: str, language: str \| None | Program code snippets with optional syntax highlighter hint. | |
DataBlock | 'data' | data: dict, schema_id: str \| None | Structured JSON data payload tied to a specific schema. | |
ErrorBlock | 'error' | error_type: str, message: str, recoverable: bool | Standardized execution/system error blocks. | |
| Media | ImageBlock | 'image' | url: str \| None, data: bytes \| None, file_id: str \| None | Image reference, inline bytes, or storage file ID. |
AudioBlock | 'audio' | url: str \| None, data: bytes \| None, transcript: str \| None | Audio data and optional speech-to-text transcript. | |
VideoBlock | 'video' | url: str \| None, data: bytes \| None | Video files or URLs. | |
DocumentBlock | 'document' | url: str \| None, data: bytes \| None, filename: str \| None | Documents (e.g. PDF/DOCX) attached to context. | |
| Agentic | ToolUseBlock | 'tool_use' | call_id: str, tool_name: str, arguments: dict | Model request to execute a specific tool with arguments. |
ToolResultBlock | 'tool_result' | call_id: str, content: list[ContentBlock], is_error: bool | Tool output payload (can be nested multimodal blocks). | |
ThinkingBlock | 'thinking' | content: str, redacted: bool | Internal model chain-of-thought/reasoning trace. | |
UIResourceBlock | 'ui_resource' | uri: str, render_mode: str | Sandbox visual interface metadata for frontend rendering. |
Key points¶
- All blocks are frozen Pydantic models. They are immutable once created.
ToolResultBlock.contentis itself alist[ContentBlock]— a tool can return images, code, data, errors, or any mix.ThinkingBlockstores extended chain-of-thought from Anthropic extended thinking. Theredactedflag lets the UI hide raw reasoning from users.UIResourceBlockis the narrow waist for interactive UIs. A tool emits aui://nameURI;ravi-uirenders it as a sandboxed iframe. The LLM only seestext— never the iframe.ErrorBlockoverTextBlock— useErrorBlockwhen a tool fails so consumers can detect errors programmatically without string-matching.register_block_type(cls)extends the discriminator registry for custom block types. Call once at module load time.content_block_from_dict(data)deserializes raw dicts. Unknowntypevalues becomeUnknownBlock— no data loss in mixed-version deployments.
AgentId and TopicId — Routing Addresses¶
| Class | Fields | Purpose & String Format | Example |
|---|---|---|---|
AgentId | type: strkey: strnamespace: str = 'default' | Point-to-point routing address.[namespace/]type/key | AgentId("react", "sess-123")→ react/sess-123 |
TopicId | type: strsource: str = 'default'namespace: str = 'default' | Pub/sub channel address.[namespace/]type/source | TopicId("agent.progress", run_id)→ agent.progress/run-abc |
AgentId is the point-to-point routing key — send a message to one specific agent instance.
TopicId is the pub/sub routing key — emit on a topic; every follower gets the message.
Standard topic conventions (enforced at L1, not kernel):
| Topic | Purpose |
|---|---|
agent.progress / {run_id} | All progress events for one run tree — one subscription covers the whole tree |
agent.stream / {agent_id.key} | Token stream from one specific agent |
Usage — Token Accounting¶
| Field | Type | Description |
|---|---|---|
input_tokens | int | Total input/prompt tokens sent to the LLM. |
cached_tokens | int | Input tokens resolved from cache (subset of input_tokens, billed lower). |
output_tokens | int | Total completion/output tokens generated by the LLM. |
reasoning_tokens | int | Output tokens spent on internal reasoning/thinking (subset of output_tokens). |
total_tokens | int | (Property) Sum of input_tokens + output_tokens. |
Usage is additive (a + b works). Every LLMResponse carries one. The L1 ExecutionTracker accumulates them to enforce ExecutionBudget.max_tokens.
KernelErrors — Typed Runtime Failures¶
The kernel error system uses a structured hierarchy for deterministic error handling:
KernelError(Base exception for all framework errors)AgentNotFoundError: Sent when a message is routed to an unregisteredAgentId.HandlerError: Raised when an agent message handler (on_message) crashes internally.AgentCrashError: Raised when the worker runner crashes or loses its lease unexpectedly.BudgetExhaustedError: Raised when token counts, monetary cost, or turn budgets are hit.MiddlewareTermination: Raised to abort execution from a middleware guard (e.g. rate limit, content warning).CancellationError: Raised when cooperative cancellation triggers or a deadline passes.ConcurrentAppendError: Raised when sequence mismatch occurs while appending to an agent'sEventLog.SpawnDenied: Raised when enqueuing a child run exceeds the tree's configuredSpawnBudget.
AgentCrashError — the orchestrator catches this, consults the retry policy, and re-dispatches the crashed agent from the last checkpoint.
MiddlewareTermination vs AgentCrashError — termination is intentional (policy blocked the run); crash is unexpected (agent code threw).
ConcurrentAppendError — two workers tried to write to the same EventLog simultaneously. Callers reload last_seq and retry. This fences concurrent writes without a distributed lock.