Building Agents with ya-agent-sdk
Build agents with the 2.0 capability-first runtime. Pydantic AI capabilities are the
only public behavior-composition surface. Do not pass SDK tools= or toolsets= to
create_agent(), slice toolsets for children, or use removed MessageBus/generated
subagent APIs.
Start Here
- Construct an unentered runtime with
create_agent().
- At application startup, call
pydantic_ai.prices.update_in_background() and retain
its handle until shutdown (stop()). Do not restart it per run. SDK runtimes do not
enable price downloads themselves; YAACLI and YA Claw manage this for their users.
- Put every agent behavior in the ordered
capabilities= list.
- Validate durable static specs with
validate_agent_spec_capabilities() before
fingerprinting or persistence; runtime entry still validates dynamic contributions.
- Enter
AgentRuntime before accessing runtime.agent or resolved capabilities.
- Use
stream_agent() for SDK lifecycle events, native steering, and recovery.
- Persist both Pydantic AI message history and
runtime.ctx.export_state().
- Use native
AgentSpec for declarative agent fields.
- Use
SubagentSpec, SubagentPlanResolver, SubagentRegistry, and
SubagentExecutionService for delegation.
- Use
DeferredInteractionResolver for approvals and external deferred calls.
Read the focused references before changing the corresponding subsystem:
Installation
pip install 'ya-agent-sdk[all]'
uv add 'ya-agent-sdk[all]'
Use selective extras such as docker, web, document, s3, tool-proxy,
oauth, or rs when a smaller installation is needed.
Core Workflows
Create and enter a runtime
from ya_agent_sdk.agents.main import create_agent
from ya_agent_sdk.capabilities import RuntimeFoundationCapability
runtime = create_agent(
"anthropic:claude-sonnet-4",
capabilities=[RuntimeFoundationCapability()],
)
async with runtime:
result = await runtime.agent.run("Summarize this project", deps=runtime.ctx)
print(result.output)
create_agent() returns an unentered AgentRuntime. Runtime entry first enters the
Environment and context, collects their contribution groups, validates capability
ordering and singleton constraints, and then constructs the Pydantic AI Agent.
Compose SDK features
from ya_agent_sdk.agents.main import create_agent
from ya_agent_sdk.capabilities import (
FilesystemCapability,
RuntimeFoundationCapability,
ShellCapability,
ToolApprovalCapability,
ToolObservationCapability,
ToolSupersessionCapability,
ToolTimeoutCapability,
ToolVisibilityCapability,
)
runtime = create_agent(
"anthropic:claude-sonnet-4",
capabilities=[
RuntimeFoundationCapability(),
FilesystemCapability(),
ShellCapability(),
ToolSupersessionCapability(),
ToolVisibilityCapability(),
ToolApprovalCapability(tools=frozenset({"shell_exec"})),
ToolObservationCapability(),
ToolTimeoutCapability(),
],
)
Capabilities own tools, instructions, request/history hooks, and run-local state as one
coherent feature. RuntimeFoundationCapability is explicit; create_agent() does not
inject it.
Stream responses
from ya_agent_sdk.agents.main import create_agent, stream_agent
from ya_agent_sdk.capabilities import RuntimeFoundationCapability
runtime = create_agent(
"openai-chat:gpt-4o",
capabilities=[RuntimeFoundationCapability()],
)
async with stream_agent(runtime, "Hello") as streamer:
async for event in streamer:
print(event)
streamer.raise_if_exception()
Use the SDK stream driver instead of manually advancing Pydantic AI graph nodes when
you need SDK lifecycle events, logical-run input routing, usage snapshots, or recovery.
Persist and restore sessions
from ya_agent_sdk.agents.main import create_agent
async with create_agent("openai-chat:gpt-4o") as runtime:
result = await runtime.agent.run("Remember this", deps=runtime.ctx)
messages = result.all_messages()
state = runtime.ctx.export_state()
restored = create_agent("openai-chat:gpt-4o", state=state)
# Pass `messages` as message_history on the next run.
ResumableState stores SDK context state, not canonical Pydantic AI message history.
Hosts persist both.
Add deferred host interaction
from pydantic_ai import DeferredToolRequests
from ya_agent_sdk.agents.main import create_agent
from ya_agent_sdk.capabilities import (
RuntimeFoundationCapability,
ToolApprovalCapability,
UserInteractionCapability,
)
runtime = create_agent(
"anthropic:claude-sonnet-4",
capabilities=[
RuntimeFoundationCapability(),
UserInteractionCapability(),
ToolApprovalCapability(tools=frozenset({"shell_exec"})),
],
output_type=[str, DeferredToolRequests],
)
The host must present every deferred request and resume with matching
DeferredToolResults. Use the typed DeferredInteractionResolver; do not inspect a
runtime-private toolset.
Add portable subagents
Define each child with native AgentSpec inside the thin YA SubagentSpec envelope,
resolve it against one immutable capability catalog, register the resulting plan, and
inject one DelegationCapability backed by a store and driver. See
./subagent.md for a complete example and durability boundaries.
Public Boundary Checklist
capabilities= is the sole public composition plane.
- Plugin entry points only add explicitly selected types to one immutable catalog;
they never grant behavior or load ambiently.
- A plugin manifest may append root grants, but named children and self forks receive
only their own explicit native grants.
AgentSpec owns model, settings, instructions, output schema, and serialized
capability definitions.
SubagentSpec adds only delegation policy.
- Named children receive only capabilities declared in their own native spec.
- Self forks rebuild an explicit policy and bounded history snapshot; they never clone
live parent capabilities.
ToolVisibilityCapability is the final child execution-boundary defense.
- Steering uses Pydantic AI
AgentRun.enqueue() through LogicalRunInputRouter.
- Durable hosts persist input before acknowledgement and keep canonical delivery in
their inbox/store. SDK lifecycle events and UI projections are notifications only.
- There is no MessageBus, generated delegate class, implicit tool inheritance, or
runtime compatibility layer in 2.0.
Reference Routing
| Topic |
Local path |
Read when |
| Context and sessions |
./context.md |
Persisting context, history, or custom context fields |
| Streaming and hooks |
./streaming.md |
Streamed UX, recovery, or lifecycle extensions |
| Events |
./events.md |
Consuming SDK or feature lifecycle events |
| Tools and policies |
./toolset.md |
Writing BaseTool adapters or execution-policy capabilities |
| Capability plugins |
./plugins.md |
Packaging plugins or adding file-based loading to a host |
| Structured input |
./user-input.md |
Approval or external deferred continuation |
| Native Tool Search |
./tool-search.md |
Deferred native capabilities and large tool libraries |
| Subagents |
./subagent.md |
Child specs, resolution, services, stores, or drivers |
| Environment |
./environment.md |
Filesystem, shell, resources, and lifecycle authority |
| Resumable resources |
./resumable-resources.md |
Reconstructing long-lived external resources |
| Skills |
./skills.md |
SDK skill catalog loading and refresh |
| Model configuration |
./model.md |
Models, settings, wrappers, and presets |
| Media |
./media.md |
Image, audio, video, and file inputs |
| Tool proxy |
./tool-proxy.md |
Search/proxy wrappers around external toolsets |
| CodeAct |
./codeact.md |
Restricted Python orchestration |
Runnable Examples
The paths below point to repository sources. Installed and bundled skill artifacts carry
the same files under ./examples/.
../../examples/general.py: capability composition, streaming, typed HITL,
persistence, named delegation, and self fork.
../../examples/deepresearch.py: autonomous capability-first research agent with
structured output.
../../examples/capability_plugin/: installable custom capability package with
metadata-only discovery, explicit catalog selection, AgentSpec reconstruction, and
a credential-free smoke run.
After editing this canonical skill, run scripts/sync-skills.sh to update YAACLI's
bundled copy.
1---2name: agent-builder3description: Build and configure AI agents with ya-agent-sdk and Pydantic AI. Covers capability-first create_agent(), stream_agent(), AgentSpec, AgentContext, ResumableState, portable subagents, environments, native steering, and deferred HITL. Use when implementing agent applications, composing capabilities, restoring sessions, configuring child-agent plans, adding approval flows, or working with ya-agent-sdk runtime APIs.4---56# Building Agents with ya-agent-sdk78Build agents with the 2.0 capability-first runtime. Pydantic AI capabilities are the9only public behavior-composition surface. Do not pass SDK `tools=` or `toolsets=` to10`create_agent()`, slice toolsets for children, or use removed MessageBus/generated11subagent APIs.1213## Start Here1415- Construct an unentered runtime with `create_agent()`.16- At application startup, call `pydantic_ai.prices.update_in_background()` and retain17 its handle until shutdown (`stop()`). Do not restart it per run. SDK runtimes do not18 enable price downloads themselves; YAACLI and YA Claw manage this for their users.19- Put every agent behavior in the ordered `capabilities=` list.20- Validate durable static specs with `validate_agent_spec_capabilities()` before21 fingerprinting or persistence; runtime entry still validates dynamic contributions.22- Enter `AgentRuntime` before accessing `runtime.agent` or resolved capabilities.23- Use `stream_agent()` for SDK lifecycle events, native steering, and recovery.24- Persist both Pydantic AI message history and `runtime.ctx.export_state()`.25- Use native `AgentSpec` for declarative agent fields.26- Use `SubagentSpec`, `SubagentPlanResolver`, `SubagentRegistry`, and27 `SubagentExecutionService` for delegation.28- Use `DeferredInteractionResolver` for approvals and external deferred calls.2930Read the focused references before changing the corresponding subsystem:3132- Sessions: [`./context.md`](./context.md)33- Streaming and events: [`./streaming.md`](./streaming.md), [`./events.md`](./events.md)34- Capability-owned tools and policies: [`./toolset.md`](./toolset.md)35- Installable capability plugins and application loading: [`./plugins.md`](./plugins.md)36- Structured deferred input: [`./user-input.md`](./user-input.md)37- Portable subagents: [`./subagent.md`](./subagent.md)38- Environment authority: [`./environment.md`](./environment.md),39 [`./resumable-resources.md`](./resumable-resources.md)40- Tool Search, proxying, and CodeAct: [`./tool-search.md`](./tool-search.md),41 [`./tool-proxy.md`](./tool-proxy.md), [`./codeact.md`](./codeact.md)4243## Installation4445```bash46pip install 'ya-agent-sdk[all]'47uv add 'ya-agent-sdk[all]'48```4950Use selective extras such as `docker`, `web`, `document`, `s3`, `tool-proxy`,51`oauth`, or `rs` when a smaller installation is needed.5253## Core Workflows5455### Create and enter a runtime5657```python58from ya_agent_sdk.agents.main import create_agent59from ya_agent_sdk.capabilities import RuntimeFoundationCapability6061runtime = create_agent(62 "anthropic:claude-sonnet-4",63 capabilities=[RuntimeFoundationCapability()],64)6566async with runtime:67 result = await runtime.agent.run("Summarize this project", deps=runtime.ctx)68 print(result.output)69```7071`create_agent()` returns an unentered `AgentRuntime`. Runtime entry first enters the72Environment and context, collects their contribution groups, validates capability73ordering and singleton constraints, and then constructs the Pydantic AI `Agent`.7475### Compose SDK features7677```python78from ya_agent_sdk.agents.main import create_agent79from ya_agent_sdk.capabilities import (80 FilesystemCapability,81 RuntimeFoundationCapability,82 ShellCapability,83 ToolApprovalCapability,84 ToolObservationCapability,85 ToolSupersessionCapability,86 ToolTimeoutCapability,87 ToolVisibilityCapability,88)8990runtime = create_agent(91 "anthropic:claude-sonnet-4",92 capabilities=[93 RuntimeFoundationCapability(),94 FilesystemCapability(),95 ShellCapability(),96 ToolSupersessionCapability(),97 ToolVisibilityCapability(),98 ToolApprovalCapability(tools=frozenset({"shell_exec"})),99 ToolObservationCapability(),100 ToolTimeoutCapability(),101 ],102)103```104105Capabilities own tools, instructions, request/history hooks, and run-local state as one106coherent feature. `RuntimeFoundationCapability` is explicit; `create_agent()` does not107inject it.108109### Stream responses110111```python112from ya_agent_sdk.agents.main import create_agent, stream_agent113from ya_agent_sdk.capabilities import RuntimeFoundationCapability114115runtime = create_agent(116 "openai-chat:gpt-4o",117 capabilities=[RuntimeFoundationCapability()],118)119120async with stream_agent(runtime, "Hello") as streamer:121 async for event in streamer:122 print(event)123 streamer.raise_if_exception()124```125126Use the SDK stream driver instead of manually advancing Pydantic AI graph nodes when127you need SDK lifecycle events, logical-run input routing, usage snapshots, or recovery.128129### Persist and restore sessions130131```python132from ya_agent_sdk.agents.main import create_agent133134async with create_agent("openai-chat:gpt-4o") as runtime:135 result = await runtime.agent.run("Remember this", deps=runtime.ctx)136 messages = result.all_messages()137 state = runtime.ctx.export_state()138139restored = create_agent("openai-chat:gpt-4o", state=state)140# Pass `messages` as message_history on the next run.141```142143`ResumableState` stores SDK context state, not canonical Pydantic AI message history.144Hosts persist both.145146### Add deferred host interaction147148```python149from pydantic_ai import DeferredToolRequests150from ya_agent_sdk.agents.main import create_agent151from ya_agent_sdk.capabilities import (152 RuntimeFoundationCapability,153 ToolApprovalCapability,154 UserInteractionCapability,155)156157runtime = create_agent(158 "anthropic:claude-sonnet-4",159 capabilities=[160 RuntimeFoundationCapability(),161 UserInteractionCapability(),162 ToolApprovalCapability(tools=frozenset({"shell_exec"})),163 ],164 output_type=[str, DeferredToolRequests],165)166```167168The host must present every deferred request and resume with matching169`DeferredToolResults`. Use the typed `DeferredInteractionResolver`; do not inspect a170runtime-private toolset.171172### Add portable subagents173174Define each child with native `AgentSpec` inside the thin YA `SubagentSpec` envelope,175resolve it against one immutable capability catalog, register the resulting plan, and176inject one `DelegationCapability` backed by a store and driver. See177[`./subagent.md`](./subagent.md) for a complete example and durability boundaries.178179## Public Boundary Checklist180181- `capabilities=` is the sole public composition plane.182- Plugin entry points only add explicitly selected types to one immutable catalog;183 they never grant behavior or load ambiently.184- A plugin manifest may append root grants, but named children and self forks receive185 only their own explicit native grants.186- `AgentSpec` owns model, settings, instructions, output schema, and serialized187 capability definitions.188- `SubagentSpec` adds only delegation policy.189- Named children receive only capabilities declared in their own native spec.190- Self forks rebuild an explicit policy and bounded history snapshot; they never clone191 live parent capabilities.192- `ToolVisibilityCapability` is the final child execution-boundary defense.193- Steering uses Pydantic AI `AgentRun.enqueue()` through `LogicalRunInputRouter`.194- Durable hosts persist input before acknowledgement and keep canonical delivery in195 their inbox/store. SDK lifecycle events and UI projections are notifications only.196- There is no MessageBus, generated delegate class, implicit tool inheritance, or197 runtime compatibility layer in 2.0.198199## Reference Routing200201| Topic | Local path | Read when |202| -------------------- | ------------------------------------------------------ | ---------------------------------------------------------- |203| Context and sessions | [`./context.md`](./context.md) | Persisting context, history, or custom context fields |204| Streaming and hooks | [`./streaming.md`](./streaming.md) | Streamed UX, recovery, or lifecycle extensions |205| Events | [`./events.md`](./events.md) | Consuming SDK or feature lifecycle events |206| Tools and policies | [`./toolset.md`](./toolset.md) | Writing BaseTool adapters or execution-policy capabilities |207| Capability plugins | [`./plugins.md`](./plugins.md) | Packaging plugins or adding file-based loading to a host |208| Structured input | [`./user-input.md`](./user-input.md) | Approval or external deferred continuation |209| Native Tool Search | [`./tool-search.md`](./tool-search.md) | Deferred native capabilities and large tool libraries |210| Subagents | [`./subagent.md`](./subagent.md) | Child specs, resolution, services, stores, or drivers |211| Environment | [`./environment.md`](./environment.md) | Filesystem, shell, resources, and lifecycle authority |212| Resumable resources | [`./resumable-resources.md`](./resumable-resources.md) | Reconstructing long-lived external resources |213| Skills | [`./skills.md`](./skills.md) | SDK skill catalog loading and refresh |214| Model configuration | [`./model.md`](./model.md) | Models, settings, wrappers, and presets |215| Media | [`./media.md`](./media.md) | Image, audio, video, and file inputs |216| Tool proxy | [`./tool-proxy.md`](./tool-proxy.md) | Search/proxy wrappers around external toolsets |217| CodeAct | [`./codeact.md`](./codeact.md) | Restricted Python orchestration |218219## Runnable Examples220221The paths below point to repository sources. Installed and bundled skill artifacts carry222the same files under `./examples/`.223224- `../../examples/general.py`: capability composition, streaming, typed HITL,225 persistence, named delegation, and self fork.226- `../../examples/deepresearch.py`: autonomous capability-first research agent with227 structured output.228- `../../examples/capability_plugin/`: installable custom capability package with229 metadata-only discovery, explicit catalog selection, `AgentSpec` reconstruction, and230 a credential-free smoke run.231232After editing this canonical skill, run `scripts/sync-skills.sh` to update YAACLI's233bundled copy.