atomr-agents
A native Rust agentic framework built as a layered actor / strategy / harness substrate on top of atomr and atomr-infer. atomr-agents gives you a single mental model — pluggable strategies that resolve under shared budgets, channelled state with first-class checkpointing, tool-call orchestration with parallel dispatch, and durable harness loops — that scales from a one-off chatbot to a multi-tenant production agent platform.
use *;
// One Pipeline composes prompt → model → parser like LCEL.
let pipeline = from
.then
.then
.build;
let answer = pipeline.call.await?;
Python parity
The Python facade ships every Rust capability. The native extension
atomr_agents._native is split into 28 hierarchical submodules:
foundational (errors, core, callable_, strategy,
instruction, context, state, observability, cache,
parser, registry); tool / skill / memory / retrieval / ingest
(tool, skill, memory, embed, retriever, ingest,
persona); agent / workflow / harness / org / eval (agent,
workflow, harness, org, eval); voice (stt, tts,
voice, voice_extras); plus the guest registry. The
top-level package re-exports the most-used classes, ships a PEP 561
py.typed marker, and exposes async coroutines / async iterators
over pyo3-async-runtimes.
Install
For an editable workflow against the local checkout:
Host-mode async event stream
EventBus.stream() returns an EventStream that implements the
Python async iterator protocol. Drive a producer on the same loop
and consume events as they fire:
=
=
break
Async registry publish
Registry.publish_async returns a Python awaitable backed by a
tokio future, so version pins land without blocking the event loop:
=
= await
Guest-mode @tool decorator
atomr_agents.guest exposes real decorators wired through
_native.guest.register_*_factory. A guest tool is a class with an
async def invoke(self, args, ctx) method:
=
return
Mirror decorators are available for the full set of 24 Rust traits:
@strategy(kind=...), @persona, @skill, @parser, @scorer,
@memory_store, @embedder, @callable_, @retriever, @loader,
@splitter, @kv_cache, @long_store, @tracer,
@conversation_agent, @diarizer, @vad, @phonemizer,
@journal, @repair_model, @persona_reconciler,
@inference_client, @ann_index. Each pairs with an
atomr_agents.<module>.*_from_factory(key) builder that
materialises the registered Python target as a Rust dyn handle.
Host-mode agent runtime
AgentBuilder assembles strategy slots into a runnable AgentRef
that implements Callable, so an agent composes with the same
decorators and pipeline operators as any other unit:
# Strategy slots come from in-process factories or Python guests.
=
=
= await
# The agent is itself a Callable — drop it into a workflow.
=
=
await
Where things live
The hierarchical layout is reflected in the Python facade — every
submodule has a one-to-one .py mirror under atomr_agents/:
The top-level package keeps the 0.2.x convenience names — so
from atomr_agents import EventBus, Registry still works.
Runtime coverage
AgentRef.run_turn, Harness.run, WorkflowRunner.run, and
Conversation are all callable from Python. The Rust runtimes are
type-erased through BoxedAgent (in crates/agent) and Box<dyn LoopStrategy> / Box<dyn TerminationStrategy> (in
crates/harness); the blanket impl Trait for Box<dyn Trait> impls
live in their respective trait crates so the composition contract
holds regardless of whether a strategy is monomorphic or boxed. See
docs/python-api.md for the full module map
and async-surface table.
Why an agentic framework, in Rust, on actors
Agentic systems don't fail because the models aren't good enough — they fail because the substrate underneath them treats context, composition, and persistence as afterthoughts. Glue-code retry policies, opaque memory, hand-rolled tool loops, brittle handoff between agents — that's where 3 a.m. pages come from.
Composition is the unit of work. A real agent is a Pipeline of
prompts, models, parsers, and tools — each with its own retry,
fallback, timeout, cache, and trace policy. atomr-agents makes every
component a Callable with the same composition surface, so
with_retry, with_fallbacks, and with_config apply uniformly to
prompts, models, retrievers, and parsers alike.
State is channelled, durable, and forkable. Long-running agents
need more than chat history. They need typed channels with
reducers (AppendMessages, MergeMap, LastWriteWins,
MaxByTimestamp), per-super-step checkpoints keyed by (workflow, run, step), and fork-with-edit so an operator can branch a
divergent run from any prior state. atomr-agents ships LangGraph's
state model verbatim in atomr's actor idiom.
Tool calls are parallel and provider-agnostic. When a model emits
five tool calls in one turn, atomr-agents fans them into a JoinSet
and aggregates in original order. The streaming tool_call_delta
parser handles OpenAI and Anthropic deltas natively; new providers
plug in behind the same Provider enum. Per-call deltas are also
surfaced as Event::ToolCallStreamed so tracers and UIs see tool
intent in real time, distinct from the post-call Event::ToolInvoked.
RichTool returns ToolReturn::{Content, ContentAndArtifact, Command}
so a tool can also drive graph control flow.
Provider runtimes are opt-in feature flags. Enable
provider-anthropic, provider-openai, or provider-gemini on the
umbrella to pull the corresponding atomr-infer-runtime-* crate and
re-export its *Config / *Pricing / *Runner via
atomr_agents::agent::providers::{anthropic, openai, gemini}. Cost
reports include cached_tokens (Anthropic prompt-cache, OpenAI cached
input) and reasoning_tokens (o1-style) automatically.
Granular efficiency. Rust gives us deterministic resource use,
zero-cost abstractions, and ownership-as-concurrency-safety. Strategy
trait generics monomorphize the per-turn pipeline; Box<dyn> opt-in
exists for config-driven loading. The whole 26-crate workspace builds
under cargo check --workspace in seconds and ships zero runtime
overhead beyond what the actor crate already pays.
What's in the box
| Crate | What it does |
|---|---|
atomr-agents |
Umbrella facade re-exporting the public surface, feature-flag-driven |
atomr-agents-core |
Ids, budgets (token / time / money / iteration), AgentContext, RunId, structured Event taxonomy, error types |
atomr-agents-callable |
Callable trait, CallableHandle, Pipeline builder (then / fan_out / assign), decorators (with_retry / with_fallbacks / with_config / with_timeout / Branch / Lambda) |
atomr-agents-strategy |
Strategy trait family (ToolStrategy, MemoryStrategy, SkillStrategy, RoutingStrategy, PolicyStrategy, LoopStrategy, TerminationStrategy) + combinators |
atomr-agents-context |
ContextAssembler — priority-merge under a TokenBudget |
atomr-agents-observability |
EventBus, RunTree builder, Tracer trait, StdoutTracer / JsonlTracer / LangSmithTracer |
atomr-agents-state |
StateSchema + 5 reducers, RunState, Checkpointer trait + InMemoryCheckpointer, fork-with-edit; SQLite/Postgres backend stubs behind features |
atomr-agents-tool |
Tool / RichTool traits, ToolDescriptor, ToolSet + ToolSetRegistry, PermissionSpec, provider-aware ToolCallParser (OpenAI / Anthropic), HandoffTool |
atomr-agents-skill |
Skill, SkillSet, Static / Keyword skill strategies |
atomr-agents-memory |
MemoryStore (short-term) + LongStore (long-term, namespace-tupled), RecencyMemoryStrategy / SummarizingMemoryStrategy / ChainedMemoryStrategy, WriteMemoryTool / UpdateMemoryTool / RecallMemoryTool |
atomr-agents-embed |
Embedder trait, MockEmbedder, AnnIndex + InMemoryAnnIndex, EmbeddingToolStrategy |
atomr-agents-retriever |
Retriever zoo: Bm25 / Vector / MultiQuery / ContextualCompression / ParentDocument / Ensemble (RRF) / SelfQuery / EmbeddingsFilter / TimeWeighted |
atomr-agents-ingest |
Loader (text / md / json / csv) + splitters (Recursive / MarkdownHeader / Code / Token / Semantic) + CachedEmbedder + IngestPipeline |
atomr-agents-persona |
All five structural strategies (Static, BigFive, Mbti, Jungian, Composite) + emphasis strategies (Static, AudienceAdaptive, TaskAdaptive, MoodState, GoalConditioned) |
atomr-agents-instruction |
ComposedInstructionStrategy<P, T, B>, ChatPromptTemplate, MessagesPlaceholder, FewShotChatTemplate, LengthBasedSelector / SemanticSimilaritySelector |
atomr-agents-agent |
Agent<I, T, Ms, Sk> actor + per-turn pipeline, tool-call loop with parallel dispatch, AgentMiddleware (logging / retry / rate-limit / redaction / tool-error-recovery), InferenceClient adapter for any ModelRunner |
atomr-agents-workflow |
DAG primitives, WorkflowRunner, StatefulRunner (channelled state), Interruptible (interrupt() + interrupt_before / _after + Command::{Continue, Resume, Update, Goto}), Subgraph, dispatch_fan_out (Send-API analogue) |
atomr-agents-harness |
Harness<L, T> actor, LoopStrategy / TerminationStrategy, durable iteration log; Harness is itself a Callable |
atomr-agents-org |
Org / Department / Team, OrgRoutingStrategy impls (RoundRobin / LoadAware / CapabilityMatch), Policy::narrow, NamespacedMemory (read-cascade + write-gating), swarm_loop helper |
atomr-agents-registry |
Versioned artifact registry with (kind, id, version) keys + publish_gated for eval-regression blocking |
atomr-agents-eval |
EvalSuite, Scorer (Contains / Equality / Regex / LlmJudgeScorer / RubricScorer / PairwiseScorer), RegressionGate, AnnotationQueue |
atomr-agents-cache |
LlmCache trait + InMemoryLlmCache + SemanticLlmCache (cosine match on prompt embedding); SQLite/Redis backend stubs behind features |
atomr-agents-parser |
Parser<T> trait, JsonParser / JsonSchemaParser / SchemaParser<T> / EnumParser / CommaListParser / XmlParser / YamlParser, OutputFixingParser, RetryWithErrorParser, StreamingPartialJsonParser |
atomr-agents-stt-core |
SpeechToText / StreamingSession traits, Capabilities (advertised per backend via a pub const), AudioInput / Transcript / StreamEvent, MockSpeechToText |
atomr-agents-stt-remote-core |
Shared HTTP / WebSocket plumbing for cloud STT backends: reqwest client builder, tokio-tungstenite connect helper, SecretRef (env / literal / file), retry / rate-limit / timeout config |
atomr-agents-stt-audio |
symphonia-based decoder, rubato resampler, and (feature mic) cpal-based MicCaptureSession with backpressure-aware mpsc producer |
atomr-agents-stt-runtime-openai |
OpenAI Whisper / gpt-4o-transcribe REST batch backend |
atomr-agents-stt-runtime-deepgram |
Deepgram REST + WebSocket backend; speaker-count diarization, partial results, VAD endpointing |
atomr-agents-stt-runtime-assemblyai |
AssemblyAI REST upload + Universal-Streaming WebSocket; named-speaker diarization |
atomr-agents-stt-runtime-whisper |
Local whisper.cpp via whisper-rs (gated behind the whisper-cpp feature). Optional download-models helper fetches ggml weights |
atomr-agents-stt-diarize-sherpa |
Diarizer trait, MockDiarizer, sherpa-onnx-backed SherpaDiarizer (gated behind sherpa-onnx), apply_to_transcript stitching |
atomr-agents-stt-voice |
VoiceSession (Live vs TurnBased { silence_ms }), Vad trait + EnergyVad/SileroVad, pump_mic_to_stream glue |
atomr-agents-stt-tool |
TranscribeTool (a Tool the model can call) and voice_input_skill(stt) -> (Skill, DynTool) for declarative agent integration |
atomr-agents-agent-sdk-core |
Provider-neutral Claude Agent SDK contract: AgentSdkConfig (mirrors ClaudeAgentOptions), normalized AgentSdkMessage / ResultSummary / AgentSdkEvent, the pluggable AgentSdkBackend / AgentSdkSession trait seam, and a deterministic MockBackend (network-free, no claude CLI) |
atomr-agents-agent-sdk-harness |
Wraps Anthropic's programmable Claude Code agent (claude-agent-sdk) as a Callable: slash commands, subagents, hooks, MCP, permission modes, sessions, custom system prompts; session registry under a TOCTOU-safe quota, SpendLedger credit tracking, .claude/ projection; behind actor, the interactive session is an atomr_core::actor::Actor; behind sandbox, per-session isolated microVM workspaces (Pattern C) |
atomr-agents-agent-sdk-harness-web |
Axum REST + SSE companion over an AgentSdkHarness (/run, /sessions…, /events, /healthz) |
atomr-agents-sandbox-core |
Backend-agnostic microVM sandbox contract: SandboxBackend / SandboxHandle traits, the 5 SandboxProfile toolchains, ResourceBudget (2 GB / 2 vCPU Rust floor), SandboxEvent, and a deterministic MockBackend so the whole surface is testable with no Docker / KVM |
atomr-agents-sandbox-harness |
Sandbox orchestration: pluggable backend, live-sandbox registry, TOCTOU-safe concurrency quota, BestFitScheduler bin-packing, warm SnapshotPool, SandboxEvent broadcast; ephemeral one-shot + persistent registry paths; itself a Callable |
atomr-agents-sandbox-tool |
The execute_in_sandbox Tool — runs untrusted Python / Bash / JS / Rust in an ephemeral sandbox, applying the Rust floor, returning { exec_id, exit_code, success, stdout, stderr, timed_out } |
atomr-agents-sandbox-backend-docker |
Docker "insecure dev mode" backend (bollard): one long-lived container per sandbox, tar-based file I/O confined to /workspace, commit-based snapshot/fork. Not a security boundary — that's Firecracker's job |
atomr-agents-sandbox-proto |
Host↔guest wire protocol: length-prefixed postcard frames (u32 LE + body, 64 MiB cap) over AF_VSOCK; keeps the in-VM guest a tiny static binary |
atomr-agents-sandbox-guest-agent |
In-VM PID-1 daemon serving the protocol: per-language exec, /workspace-confined file I/O, best-effort init; lean static musl build |
atomr-agents-sandbox-harness-web |
Axum REST + SSE companion over a SandboxHarness (/run, /sandboxes…, /events, /healthz) |
atomr-agents-py-bindings |
atomr_agents._native PyO3 module — 28 hierarchical submodules exposing every framework capability to Python (callable composition, strategies, instruction templates, memory + retriever zoo + ingest, agent / workflow / harness runtimes via BoxedAgent, eval, tracers, voice + conversation, 24 guest-trait decorators) |
atomr-agents-cli |
atomr-agents binary with eval / registry / harness / serve (Studio-style read+resume inspector) subcommands |
atomr-agents-testkit |
Stub crate today. For tests, depend on atomr-infer-testkit (re-exports MockRunner / MockScript) directly — that's what crates/agent tests use. |
Plus a Python facade — pip install atomr-agents — that exposes the
host-mode Registry / EventBus and the guest-mode @tool /
@strategy / @persona decorators.
Untrusted code execution — the microVM sandbox. Seven sandbox-*
crates give an agent secure, instant-boot compute to run model-authored
Python / Bash / JS / Rust. A backend-agnostic contract
(SandboxBackend / SandboxHandle) sits under a quota'd orchestration
harness (bin-packing scheduler + warm snapshot pool), the
execute_in_sandbox tool, an AF_VSOCK host↔guest protocol, an in-VM
PID-1 guest agent, a REST/SSE web companion, and the
atomr_agents.sandbox Python facade. Backends escalate by isolation
strength — deterministic mock (CI) → Docker "insecure dev mode" →
Firecracker microVM (the real boundary) → Tier-3 gRPC cluster. Full
write-up in docs/sandbox-architecture.md.
Programmable Claude Code — the Agent SDK harness. Three agent-sdk-*
crates wrap Anthropic's claude-agent-sdk
(the programmable form of Claude Code) as a Callable, exposing Claude
Code's full harness — slash commands, subagents, hooks, MCP, permission
modes, sessions, custom system prompts, and the built-in tool set — billed
against your Anthropic API credits via the bundled claude CLI. A
provider-neutral contract (AgentSdkConfig + AgentSdkBackend /
AgentSdkSession, normalized message/event schema) sits under the
orchestration harness (credit-tracking SpendLedger, .claude/ projection,
session registry), a REST/SSE web companion, and the atomr_agents.agent_sdk
Python facade — whose interactive session is exposed into the atomr actor
model. Behind the sandbox feature, Pattern C gives each session its own
isolated microVM workspace: the agent's
exec/file is routed into the sandbox (host Bash/Write/Edit disabled) and
the workspace is discarded — or snapshotted — on close, containing the
bypassPermissions default for untrusted work. The contract is deliberately
provider-neutral: because the harness
only sees a normalized schema behind the backend trait, other vendors that
mirror Anthropic's Agent SDK structure (with small option/message
differences) plug in by supplying a thin adapter — no harness changes. Full
write-up, including the generalization recipe, in
docs/agent-sdk-harness.md.
Quick start (Rust)
The umbrella crate is published on crates.io as atomr-agents:
[]
= { = "0.2", = ["agent", "harness", "eval"] }
= { = "0.6", = ["openai"] } # or any provider
Or, to pull a provider runtime through the umbrella so Agent /
LocalRunnerClient / OpenAiRunner come from one crate:
= { = "0.2", = ["agent", "provider-openai"] }
# or features = ["agent", "provider-anthropic"], ["agent", "provider-gemini"]
A minimal agent against MockRunner (good for tests; swap for any
ModelRunner in production):
use Arc;
use *;
use ;
use ;
use ;
use StaticSkillStrategy;
use StaticPersonaStrategy;
use ;
use EventBus;
use ;
let runner = new;
let inference: =
new;
let agent = Agent ;
let r = agent
.run_turn
.await?;
println!;
Add tools, switch the MockRunner to a real ModelRunner (OpenAI,
Anthropic, vLLM, …), and the same code runs unchanged.
Quick start (Python)
=
=
See docs/python.md for the full host/guest model and the
subinterpreter-pool dispatcher pattern inherited from atomr's pycore.
Documentation map
docs/index.md is the full documentation hub. The map below
links everything from this README.
Core framework
docs/architecture.md— runtime layout, crate stack, where each layer slots indocs/state-and-checkpointing.md— channels, reducers,Checkpointer, fork/replaydocs/agent-pipeline.md— the per-turn pipeline + tool-call loop + middlewaredocs/workflows-and-hitl.md— DAG, Send-API, dynamic interrupts, breakpointsdocs/retrieval-and-ingestion.md— retriever zoo,LongStore, loaders, splittersdocs/observability.md—EventBus,RunTree, tracersdocs/eval.md— eval suites, judge / pairwise / rubric scorers, regression gatedocs/multi-agent-patterns.md— supervisor / swarm / network / hierarchicaldocs/feature-matrix.md— every feature flag, what it pulls in
Subsystems & harnesses
docs/sandbox-architecture.md— microVM sandbox: untrusted-code execution, backend tiers (mock → Docker → Firecracker → cluster), vsock protocol, guest agentdocs/coding-cli-harness.md— wraps local AI coding CLIs (Claude Code, Codex, Antigravity) as callables; headless + interactive (xterm.js) modesdocs/agent-sdk-harness.md— wraps Anthropic's programmable Claude Code agent (claude-agent-sdk) as aCallable(slash commands, subagents, hooks, MCP, sessions); the Python interactive session is exposed into the atomr actor model; includes the recipe for generalizing to other Agent-SDK-shaped providersdocs/stt-harness.md— agentic streaming speech-to-text, diarization, editable transcript review UIdocs/meetings-harness.md— attendees, notes, actions, tiered summaries over a diarized transcriptdocs/avatar-harness.md— real-time embodied agent: perception → cognition → TTS → 60 Hz LiveLink sync to a UE5 MetaHumandocs/deep-research-harness.md— multi-step, multi-source, citation-bearing research with pluggable topologiesdocs/agent-host/index.md— long-lived on-disk runtime (SOUL / RULES / MEMORY / USER / SKILL.md) giving an agent persistent identity, skills, hooks, schedules, channels
Python
docs/python.md— Python bindings + subinterpreter-pool guest modedocs/python-api.md— Python API reference: submodule map, async surfaces, 0.2 → 0.3 migration
Migration & AI-assisted coding
docs/migrating-from-langgraph.md— concept-mapping table + concrete code translationsai-skills/— Claude Code / Agent SDK skills for AI-assisted coding against atomr-agents
License
Apache-2.0.