From 2d1c7f3728a66b487312ab4666c8e23fba472ccd Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Mon, 31 Aug 2026 21:32:54 +0300 Subject: [PATCH 01/25] chore: files changed vendor/tinyinference Auto-committed-on: dragonfly Co-authored-by: Medulla --- vendor/tinyinference | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/tinyinference b/vendor/tinyinference index d2e377ae..70412ce5 160000 --- a/vendor/tinyinference +++ b/vendor/tinyinference @@ -1 +1 @@ -Subproject commit d2e377ae19a6d27785927f4564526653ae8a8906 +Subproject commit 70412ce59215ac73d61385cf782603e9c046e004 From 4bf2e92bd6bb92dc6476a55b0c13f72abb188d46 Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Mon, 31 Aug 2026 21:35:22 +0300 Subject: [PATCH 02/25] chore: files changed README.md Auto-committed-on: dragonfly Co-authored-by: Medulla --- README.md | 413 ++++++++++++++++++++++-------------------------------- 1 file changed, 164 insertions(+), 249 deletions(-) diff --git a/README.md b/README.md index 1491b365..68b6a737 100644 --- a/README.md +++ b/README.md @@ -9,282 +9,206 @@ License: GPL v3

-**TinyAgents is a durable agent and graph harness for Rust.** It is a typed, -checkpointed runtime where language models call models, agents call agents, -graphs run graphs, and a model can author, compile, and run the very workflow it -is standing inside — all as inspectable, checkpointed, policy-checked Rust. - -## Recursion, without an embedded interpreter - -Most agent frameworks stuff everything into one ever-growing context window and -hope the model copes. TinyAgents takes the other stance: a long task is an -external *environment* that gets decomposed, and the runtime is re-entrant, so a -model can recurse over pieces of it instead of swallowing the whole thing at -once. The concrete surfaces: - -- **Sub-agents (agents calling agents).** A harness agent is exposed *as a tool* - to another agent, so orchestration is literally a model calling a model - (`SubAgent`, `SubAgentSession`, `SubAgentTool`). -- **Recursion policy + depth tracking.** The runtime tracks `root_run_id` / - `parent_run_id`, enforces a recursion limit, and rolls child runs' events, - usage, and cost up to the parent as first-class observable runs. -- **Graphs that run graphs.** A node can embed another compiled graph, so a - whole compiled workflow can appear as a single step inside another one. -- **Self-authoring (the deepest recursion).** A model can emit a `.rag` - blueprint that compiles through the *same* registry-bound compiler path as a - human-authored file, then runs on the *same* runtime the model is already - executing in. The harness can describe and re-enter itself. - -One language, one runtime: `.rag` blueprints lower into the exact same `graph` + -`harness` types as hand-written Rust — a language whose programs *are* the -runtime that interprets them. - -**Not in this workspace, by design:** the scripted CodeAct/REPL loop — an embedded -interpreter (Rhai, Python, JavaScript) executing model-written code cells whose -only host surface is capability calls. That is a host concern. TinyAgents gives -it everything it needs (the capability `registry`, the harness, typed -`SessionId`/`CellId`/`CallId`, and the `repl_agent` node kind for binding a -host-provided scripted node by name) without pulling an interpreter into your -dependency graph. - -## Features - -- **Harness** — provider-neutral model calls, typed tools, middleware, - structured output, streaming, usage/cost accounting, retries and limits, - response caching, memory/embeddings, summarization, steering, and a testkit. -- **Graph runtime** — LangGraph-style durable, typed state graphs: `START`/`END`, - nodes, edges, conditional routing, commands, `Send` fanout, reducers/channels, - checkpoints, interrupts, subgraphs, streaming, topology export, and time - travel. -- **Registry** — a named capability catalog (models, tools, agents, graphs, - stores, middleware, policy) that `.rag` binds by name. -- **`.rag` expressive language** — a declarative, side-effect-free blueprint - format that compiles (lexer → parser → compiler) into the runtime; the safe - boundary for agent-authored plans. -- **Recursion & sub-agents** — agents-as-tools, subgraphs, depth tracking, and a - recursion policy so deep call trees stay bounded and observable. -- **Durability & checkpoints** — resume long runs, replay history, and travel - back in time across superstep boundaries. -- **Provider-neutral** — one interface across hosted and local providers; swap - models without rewriting workflows. -- **Observability** — normalized events, usage, and cost that roll up across - recursive child runs. -- **Structured output & streaming** — typed responses and incremental token - streams at the harness boundary. - -## Architecture - -```text - +-----------------------+ - | .rag blueprint | - | declarative workflow | - +-----------+-----------+ - | - | compile / lower (by name) - v -+-------------+ +-------------------------------------------+ -| Application |------->| Capability Registry | -| Rust code | | models | tools | agents | graphs | policy | -+------+------+ +---------------------+---------------------+ - | | - | v - | +-------------------------------------------+ - +------------->| Durable Graph Runtime | - | typed state | nodes | edges | checkpoints | - +---------------------+---------------------+ - | - v - +-------------------------------------------+ - | Agent Harness | - | prompts | tools | middleware | usage/cost | - +----+--------------------------+-----------+ - | | - v v - +------------------+ +------------------+ - | Model Providers | | Typed Tools | - | OpenAI/Anthropic | | local functions | - | Ollama/etc. | | external systems | - +------------------+ +------------------+ -``` - -The recursion loop — agents call agents, and graphs run graphs: - -```text - +-------+ - | START | - +---+---+ - | - v - +-------------+ a sub-agent is just a tool, - | Agent Node | and a tool may itself be a - +------+------+ whole compiled graph... - | - +------+-------------------------+ - | | | - needs tool calls sub-agent done - | | | - v v v -+-----------+ +---------------+ +-----+ -| Tool Node | | SubAgent / | | END | -+-----+-----+ | Subgraph Node | +-----+ - | +-------+-------+ - | | depth +1, recursion policy, - | | child run rolls up usage/cost - +-- loops back --+--- re-enters the runtime ---+ - to Agent Node (graph -> subgraph -> graph) -``` +TinyAgents is a small, provider-neutral agent harness for Rust, plus a durable +typed state-graph runtime. It takes its shape from +[LangChain](https://www.langchain.com/) (models, tools, middleware, structured +output, streaming, usage/cost) and +[LangGraph](https://www.langchain.com/langgraph) (`START`/`END`, nodes, +conditional edges, channels/reducers, checkpoints, interrupts, subgraphs, time +travel) — rebuilt as ordinary, typed Rust with no hidden magic. + +It is for Rust services that need to call models and tools in a loop, want +that loop to be resumable and inspectable, and would rather not carry a +Python runtime or a framework's DSL to get there. + +## What's inside + +TinyAgents is a Cargo workspace, not one crate. Depend on the pieces you need: + +- **`tinyagents-harness`** — provider-neutral model calls, typed tools, + middleware, structured output, streaming, usage/cost accounting, retries, + caching, and memory. Features: `sqlite`, `tools`, `multimodal`, `tracing`. +- **`tinyagents-graph`** — a LangGraph-style durable, typed state graph: + `START`/`END`, nodes, conditional edges, `Send` fanout, reducers/channels, + checkpoints, interrupts, subgraphs, and time travel. Features: `sqlite`, + `tracing`. +- **`tinyagents-language`** — the `.rag` blueprint format: a declarative, + side-effect-free workflow description that lexes, parses, and compiles into + the same graph and harness types as hand-written Rust. +- **`tinyagents-registry`** — a named capability catalog (models, tools, + agents, graphs, routers) that `.rag` and application code bind against by + name, plus an offline model price/capability catalog. +- **`tinyagents-session`** — a SQLite-backed store for session history, + messages, tool calls, cost, and run lineage. +- **`tinyagents-tracing`** — the `tracing` macros the other crates gate behind + their `tracing` feature. Compiled out by default. +- **`tinyagents-integration-tests`** — cross-crate tests and the runnable + examples referenced below (not published, workspace-internal). + +None of the crates are published to crates.io (`publish = false` in every +`Cargo.toml`); use path or git dependencies. ## Quick start -Add only the TinyAgents crates your project uses. There is deliberately no -`tinyagents` facade crate, so migrating from the former monolith is a breaking -change: +None of the crates ship on crates.io, so add them as git or path dependencies: ```toml [dependencies] -tinyagents-harness = "2.1.1" -tinyagents-graph = "2.1.1" -tinyagents-language = "2.1.1" -tinyagents-registry = "2.1.1" -tinyagents-session = "2.1.1" +tinyagents-harness = { git = "https://github.com/tinyhumansai/tinyagents", package = "tinyagents-harness" } +tinyagents-graph = { git = "https://github.com/tinyhumansai/tinyagents", package = "tinyagents-graph" } +tinyagents-language = { git = "https://github.com/tinyhumansai/tinyagents", package = "tinyagents-language" } +tinyagents-registry = { git = "https://github.com/tinyhumansai/tinyagents", package = "tinyagents-registry" } ``` -The OpenAI (and OpenAI-compatible) provider is compiled in by default; the -build stays offline unless you actually make a call. Optional features live on -the crate that owns the behavior: `tinyagents-harness` provides `sqlite`, -`tools`, `multimodal`, and `tracing`; `tinyagents-graph` provides `sqlite` and -`tracing`; and the registry and session crates forward `tracing`. Tracing -instrumentation is disabled unless that feature is selected. +A minimal typed graph — a whole-state agent/tool loop (trimmed from +[`examples/basic_graph.rs`](crates/tinyagents-integration-tests/examples/basic_graph.rs)): -To explore locally: +```rust +use tinyagents_graph::*; +use tinyinference::message::Message; + +#[derive(Clone, Debug)] +struct AgentState { + messages: Vec, + needs_tool: bool, +} + +let graph = GraphBuilder::::overwrite() + .add_node("agent", |mut state: AgentState, _ctx: NodeContext| async move { + state.messages.push(Message::assistant("checking the local tool")); + Ok(NodeResult::Update(state)) + }) + .add_node("tool", |mut state: AgentState, _ctx: NodeContext| async move { + state.messages.push(Message::tool("echo", "tool result")); + state.needs_tool = false; + Ok(NodeResult::Update(state)) + }) + .set_entry("agent") + .add_conditional_edges( + "agent", + |state: &AgentState| if state.needs_tool { "tool".to_string() } else { "done".to_string() }, + [("tool", "tool"), ("done", END)], + ) + .add_edge("tool", "agent") + .compile()?; -```sh -git clone git@github.com:tinyhumansai/tinyagents.git -cd tinyagents -cargo run -p tinyagents-integration-tests --example basic_graph +let run = graph.run(AgentState { messages: vec![], needs_tool: true }).await?; ``` -OpenAI-backed examples need an API key: +Run it for real: ```sh -export OPENAI_API_KEY=... -cargo run -p tinyagents-integration-tests --example openai_chat +git clone git@github.com:tinyhumansai/tinyagents.git +cd tinyagents +cargo run -p tinyagents-integration-tests --example basic_graph ``` -Bound individual tool calls by installing shared timeout settings on the -harness. Tools return `ToolTimeout::Inherit` by default; they may instead opt -out with `Unbounded` or request a clamped explicit `Millis` budget: +A one-shot model call through the harness ([`examples/openai_chat.rs`](crates/tinyagents-integration-tests/examples/openai_chat.rs)): ```rust -use tinyagents_harness::{AgentHarness, ToolTimeoutSettings}; +use std::sync::Arc; +use tinyagents_harness::runtime::AgentHarness; +use tinyinference::message::Message; +use tinyinference::providers::openai::OpenAiModel; +let model = OpenAiModel::from_env()?; let mut harness: AgentHarness<()> = AgentHarness::new(); -harness.with_tool_timeout_settings(ToolTimeoutSettings::new( - 120_000, // inherited default - 1_000, // minimum explicit budget - 3_600_000, - 5_000, // scheduling grace for explicit budgets -)); -``` - -A per-tool deadline produces a recoverable tool-error message and the agent -loop continues, so the model can retry or choose another tool. The run's -wall-clock deadline remains the outer hard abort. Clones of the settings share -their inherited value, allowing a host to update it without rebuilding a -harness. +harness.register_model("openai", Arc::new(model)).set_default_model("openai"); -Export durable harness observations to Langfuse with the embedded client: - -```rust -use tinyagents_harness::{LangfuseClient, LangfuseTraceConfig}; - -let client = LangfuseClient::proxy("https://api.tinyhumans.ai", backend_jwt)?; -client - .send_observations( - LangfuseTraceConfig { - user_id: Some("user_123".to_string()), - session_id: Some("thread_abc".to_string()), - ..Default::default() - }, - &observations, - ) +let run = harness + .invoke_default(&(), vec![Message::user("What is a Rust trait?")]) .await?; +println!("{}", run.text().unwrap_or_default()); ``` -`LangfuseClient::proxy` sends to the backend -`/telemetry/langfuse/ingestion` endpoint with bearer auth. Use -`LangfuseClient::direct(langfuse_url, public_key, secret_key)` when an -application is allowed to talk to Langfuse directly. - -Graph runs export the same way through `GraphLangfuseExporter`, which reuses the -harness `LangfuseClient` transport and turns supersteps and nodes into timed -spans (failures promoted to `ERROR`), with per-node **tool health** telemetry -attached to the trace: - -```rust -use tinyagents_graph::GraphLangfuseExporter; -use tinyagents_harness::{LangfuseClient, LangfuseTraceConfig}; - -let exporter = GraphLangfuseExporter::new(LangfuseClient::from_env()?); -let observations = journal.read_from(run_id, 0).await?; -exporter - .send_observations(LangfuseTraceConfig::default(), &observations) - .await?; +```sh +export OPENAI_API_KEY=... +cargo run -p tinyagents-integration-tests --example openai_chat ``` -Because a graph run and the agent runs its nodes spawn share the same -`root_run_id` — the default Langfuse `traceId` for both exporters — exporting a -graph run and its child agents lands every step, node, model generation, and -tool call under one trace for full end-to-end observability. - -## Examples to explore +## Graph runtime + +`tinyagents-graph` is a durable, typed state graph modeled on LangGraph: +`START`/`END` markers, nodes, static and conditional edges, `Command`-based +routing, `Send` fanout, reducers over named channels, checkpointing (with an +optional `sqlite` backend), interrupts, streaming events, topology export, and +replay/time travel across superstep boundaries. A node can embed another +compiled graph as a subgraph, so a whole workflow can appear as a single step +inside a larger one. + +## Harness + +`tinyagents-harness` runs the model/tool agent loop: provider-neutral model +calls, typed tool definitions, middleware, structured output, streaming, +usage and cost accounting, retries and limits, response caching, memory, and +a testkit for exercising the loop without a live provider. An agent can be +wrapped as a tool and handed to another agent (`SubAgent` / +`SubAgentSession` / `SubAgentTool`), which is how multi-agent orchestration +is composed — plain function composition, not a distinct execution mode. + +## Registry + +`tinyagents-registry` is a name-addressable catalog of models, tools, agents, +graphs, and routers. `.rag` blueprints and application code both resolve +capabilities by name against it rather than holding direct handles, which is +what lets a blueprint be validated against exactly the capabilities a host +chose to register. + +## `.rag` blueprint language + +`tinyagents-language` implements `.rag`: a declarative, side-effect-free +format for describing a graph's state channels, nodes, routes, and named +capability references. It compiles through a fixed pipeline — +`source -> lexer -> tokens -> parser -> AST -> compiler -> Blueprint` — into +the same `tinyagents-graph` and `tinyagents-harness` types produced by +hand-written Rust. It can only reference capabilities by name; it has no way +to embed arbitrary code, so a blueprint is bound and validated against a +registry before it runs. See +[`examples/rag_blueprint.rs`](crates/tinyagents-integration-tests/examples/rag_blueprint.rs). + +## Providers + +Every provider speaks the OpenAI Chat Completions wire format, so one adapter +reaches all of them; only the base URL and model differ. Built-in presets: +OpenAI, Anthropic (via its OpenAI-compatible endpoint), DeepSeek, Groq, xAI, +OpenRouter, Together, Mistral, and Ollama (local). Any other OpenAI-compatible +endpoint works by base URL — see [`providers.env.example`](providers.env.example) +for the full list and configuration format. + +## Examples All live in [`crates/tinyagents-integration-tests/examples/`](crates/tinyagents-integration-tests/examples/): - **`basic_graph`** — a minimal typed state graph: `START`, nodes, edges, `END`. - **`complex_graph`** — conditional routing, fanout, and richer topology. -- **`durable_graph`** — checkpoints, resume, and time-travel over supersteps. -- **`resilient_graph`** — node-level retry over transient failures, plus a - resumable failure checkpoint that `retry` restarts after an outage clears. -- **`agent_loop_tools`** — the agent ↔ tool loop the harness runs. -- **`orchestrator_subagents`** — **recursion in action:** an orchestrator agent - that calls sub-agents as tools, with depth tracking and rolled-up usage. -- **`openai_self_blueprint`** — **the deepest recursion:** a model authors a - `.rag` blueprint that is compiled and run on the same runtime. -- **`rag_blueprint`** — load and run a declarative `.rag` workflow. -- **`goals_and_todos`** — a durable `ThreadGoal` driving a `TaskBoard` kanban - on one thread. +- **`durable_graph`** — checkpoints, resume, and time travel over supersteps. +- **`resilient_graph`** — node-level retry over transient failures, with a + resumable checkpoint. +- **`agent_loop_tools`** — the agent/tool loop the harness runs. +- **`orchestrator_subagents`** — an orchestrator agent that resolves and calls + sub-agents by name from the registry. +- **`rag_blueprint`** — parse and compile a `.rag` workflow, then bind it + against a registry. +- **`openai_self_blueprint`** — a model emits a `.rag` blueprint that is + compiled and run. +- **`goals_and_todos`** — a durable goal driving a task-board kanban on one + thread. +- **`openai_chat`**, **`openai_tools`**, **`openai_structured`**, + **`openai_graph_agent`** — provider-backed chat, tool calling, structured + output, and a graph-driven agent. - **`subconscious_loop`** — an offline, testable autonomous closed-loop - harness (see - [`examples/subconscious_loop/README.md`](crates/tinyagents-integration-tests/examples/subconscious_loop/README.md)). -- **`openai_chat`** — a single provider-backed chat turn. -- **`openai_tools`** — tool calling against a hosted model. -- **`openai_structured`** — typed structured output. -- **`openai_graph_agent`** — a provider-backed agent driven inside a graph. + harness (see its own + [README](crates/tinyagents-integration-tests/examples/subconscious_loop/README.md)). OpenAI-backed examples require `OPENAI_API_KEY` at run time. ## Documentation -- [Harness API](https://docs.rs/tinyagents-harness) -- [Graph API](https://docs.rs/tinyagents-graph) -- [Language API](https://docs.rs/tinyagents-language) -- [Registry API](https://docs.rs/tinyagents-registry) -- [Session API](https://docs.rs/tinyagents-session) -- [Wiki home](https://github.com/tinyhumansai/tinyagents/wiki) - - [Recursion and sub-agents](https://github.com/tinyhumansai/tinyagents/wiki/Recursion-and-RLM) - - [Harness](https://github.com/tinyhumansai/tinyagents/wiki/Harness) - - [Graph runtime](https://github.com/tinyhumansai/tinyagents/wiki/Graph-Runtime) - - [Registry](https://github.com/tinyhumansai/tinyagents/wiki/Registry) - - [Expressive language `.rag`](https://github.com/tinyhumansai/tinyagents/wiki/Expressive-Language-RAG) - - [Providers](https://github.com/tinyhumansai/tinyagents/wiki/Providers) - - [Quick start](https://github.com/tinyhumansai/tinyagents/wiki/Quick-Start) - - [Examples](https://github.com/tinyhumansai/tinyagents/wiki/Examples) - - [Development](https://github.com/tinyhumansai/tinyagents/wiki/Development) - -Contributors working directly in the repository should also read the checked-in -architecture specification under [`docs/spec/README.md`](docs/spec/README.md). +- [`docs/spec/README.md`](docs/spec/README.md) — architecture specification. +- [Wiki](https://github.com/tinyhumansai/tinyagents/wiki) — Harness, Graph + Runtime, Registry, Expressive Language, Providers, Quick Start, + Examples, Development. ## Development @@ -307,22 +231,13 @@ PROVIDER_MATRIX=1 cargo test -p tinyagents-integration-tests --test live_provide ``` Dialling is opt-in through `PROVIDER_MATRIX=1`, so a bare `cargo test` stays -offline even with a fully configured `providers.env`. - -`providers.env` is gitignored — never commit real keys. See -[`crates/tinyagents-harness/src/providers/openai/README.md`](crates/tinyagents-harness/src/providers/openai/README.md) -for the configuration format. +offline even with a fully configured `providers.env`. `providers.env` is +gitignored — never commit real keys. ## Contributing -TinyAgents welcomes focused contributions that improve the graph runtime, -harness contracts, the registry, the `.rag` language, provider -adapters, tests, examples, and documentation. - Read [CONTRIBUTING.md](CONTRIBUTING.md) before opening a pull request. ## License TinyAgents is licensed under [GPL-3.0-only](LICENSE). - -Built by TinyHumans for the Rust agent ecosystem. From 1a5210d03ff70725d3ba908f31c0752774d79efa Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Mon, 31 Aug 2026 21:35:38 +0300 Subject: [PATCH 03/25] chore: files changed docs/spec/README.md Auto-committed-on: dragonfly Co-authored-by: Medulla --- docs/spec/README.md | 58 ++++++++++----------------------------------- 1 file changed, 13 insertions(+), 45 deletions(-) diff --git a/docs/spec/README.md b/docs/spec/README.md index 186324a3..dc24114b 100644 --- a/docs/spec/README.md +++ b/docs/spec/README.md @@ -1,7 +1,11 @@ # TinyAgents System Specification -TinyAgents is a Rust-native LLM application framework inspired by LangChain and -LangGraph. The system is organized as focused crates for five public surfaces: +TinyAgents is a small, provider-neutral agent harness for Rust, plus a durable +typed state-graph runtime. It takes its shape from LangChain (models, tools, +middleware, structured output, streaming, usage/cost) and LangGraph +(`START`/`END`, nodes, conditional edges, channels/reducers, checkpoints, +interrupts, subgraphs, time travel) — rebuilt as ordinary, typed Rust. The +system is organized as five public crates: 1. the harness 2. the graph @@ -9,18 +13,12 @@ LangGraph. The system is organized as focused crates for five public surfaces: 4. the expressive language 5. durable sessions -Scripted, interpreter-backed orchestration (a CodeAct/REPL loop over -model-written code cells) is deliberately a *host* concern built on top of these -crates, not a surface this workspace ships. See "Host-side surfaces" below. - The goal is to make agent systems easy to define, inspect, run, test, and -eventually serialize without hiding the Rust types that make production systems -reliable. +serialize without hiding the Rust types that make production systems reliable. ## Reference Positioning -TinyAgents should synthesize the reference systems rather than clone any one of -them: +TinyAgents synthesizes the reference systems rather than cloning either one: - LangGraph contributes the durable execution model: explicit state graphs, virtual `START` and `END`, Pregel-style supersteps, reducers/channels, @@ -29,42 +27,12 @@ them: - LangChain contributes the harness model: provider-neutral models, tools, middleware, runtime context, memory, retrieval, structured output, tracing, usage, cost, and conformance tests for integrations. -- `rust-langgraph` shows the Rust-facing precedent for a stateful graph runtime - with nodes, conditional edges, checkpoints, streaming, optional model - adapters, and ReAct/tool helpers. TinyAgents should go deeper on typed state, - harness composition, registries, and language-backed graph definitions. -- OpenHuman PR #4261 contributes the closest product-shaped precedent: a - harness-decoupled graph engine, persistent checkpoints, HITL, graph - observability, blueprints, JSON-RPC run control, and a behavior-preserving - cutover from an implicit turn loop to an explicit phase machine. -- CodeAct/recursive-language-model runtimes contribute the recursion model: - context and prompts as runtime values, recursive sub-model or sub-agent calls - as functions, persistent session variables, and trajectory logging. TinyAgents - provides the primitives (registry capabilities, sub-agents, session/cell/call - ids, event journals); the interpreter and its sandbox stay host-side. - -The target architecture is therefore layered: the harness owns model/tool -execution and policies, the graph owns deterministic state transition and -durability, the registry owns named capabilities, and `.rag` owns serializable -graph blueprints. No layer should bypass another layer's safety, policy, -observability, or test contracts. - -## Host-side surfaces -Some things a recursive agent system needs are intentionally *not* implemented -here, because a host can implement them on top of the four modules and because -shipping them would drag an embedded interpreter into every dependent's build: - -- the scripted CodeAct/REPL session loop (an embedded Rhai / Python / JavaScript - interpreter running model-written code cells) -- the driver loop that prompts a model for the next code cell and feeds the - cell's output back in - -What these crates provide for those hosts: the capability `registry` (so a script -can only reach named `llm` / `tool` / `agent` capabilities), the harness and its -sub-agent recursion accounting, typed `SessionId` / `CellId` / `CallId`, the -event journal, and the `.rag` `repl_agent` node kind, which binds a -host-provided scripted node to a registered `Script` component by name. +The target architecture is layered: the harness owns model/tool execution and +policies, the graph owns deterministic state transition and durability, the +registry owns named capabilities, and `.rag` owns serializable graph +blueprints. No layer should bypass another layer's safety, policy, +observability, or test contracts. ## Detailed Module Docs From 71ea241048689d7af2e3123409eee2d24e6c5075 Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Mon, 31 Aug 2026 21:35:42 +0300 Subject: [PATCH 04/25] docs(readme): fold openai_chat commands into example prose Move the shell commands for running the openai_chat example into the paragraph introducing it, removing the duplicated standalone block Auto-committed-on: dragonfly Co-authored-by: Medulla --- README.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 68b6a737..a2bdc418 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,8 @@ cd tinyagents cargo run -p tinyagents-integration-tests --example basic_graph ``` -A one-shot model call through the harness ([`examples/openai_chat.rs`](crates/tinyagents-integration-tests/examples/openai_chat.rs)): +A one-shot model call through the harness (`export OPENAI_API_KEY=...` then +`cargo run -p tinyagents-integration-tests --example openai_chat`): ```rust use std::sync::Arc; @@ -121,11 +122,6 @@ let run = harness println!("{}", run.text().unwrap_or_default()); ``` -```sh -export OPENAI_API_KEY=... -cargo run -p tinyagents-integration-tests --example openai_chat -``` - ## Graph runtime `tinyagents-graph` is a durable, typed state graph modeled on LangGraph: From 066ea215e22b7c8818434081c9df2075702b6096 Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Mon, 31 Aug 2026 21:35:56 +0300 Subject: [PATCH 05/25] docs(readme): consolidate example descriptions and API key note Condense the integration example list in the README by merging the graph example summaries and moving the OpenAI API key requirement inline. This keeps the overview compact while preserving the setup detail. Auto-committed-on: dragonfly Co-authored-by: Medulla --- README.md | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index a2bdc418..7e608a57 100644 --- a/README.md +++ b/README.md @@ -176,11 +176,9 @@ for the full list and configuration format. All live in [`crates/tinyagents-integration-tests/examples/`](crates/tinyagents-integration-tests/examples/): -- **`basic_graph`** — a minimal typed state graph: `START`, nodes, edges, `END`. -- **`complex_graph`** — conditional routing, fanout, and richer topology. -- **`durable_graph`** — checkpoints, resume, and time travel over supersteps. -- **`resilient_graph`** — node-level retry over transient failures, with a - resumable checkpoint. +- **`basic_graph`**, **`complex_graph`**, **`durable_graph`**, + **`resilient_graph`** — a minimal typed graph, then conditional + routing/fanout, checkpoint/resume/time-travel, and node-level retry. - **`agent_loop_tools`** — the agent/tool loop the harness runs. - **`orchestrator_subagents`** — an orchestrator agent that resolves and calls sub-agents by name from the registry. @@ -192,13 +190,11 @@ All live in thread. - **`openai_chat`**, **`openai_tools`**, **`openai_structured`**, **`openai_graph_agent`** — provider-backed chat, tool calling, structured - output, and a graph-driven agent. + output, and a graph-driven agent (all need `OPENAI_API_KEY`). - **`subconscious_loop`** — an offline, testable autonomous closed-loop harness (see its own [README](crates/tinyagents-integration-tests/examples/subconscious_loop/README.md)). -OpenAI-backed examples require `OPENAI_API_KEY` at run time. - ## Documentation - [`docs/spec/README.md`](docs/spec/README.md) — architecture specification. From 1a9f89c6e9e8559ac70c651b0de0b96d3ba8b0fb Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Mon, 31 Aug 2026 21:36:20 +0300 Subject: [PATCH 06/25] chore: files changed docs/modules/expressive-language/reference.md Auto-committed-on: dragonfly Co-authored-by: Medulla --- docs/modules/expressive-language/reference.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/modules/expressive-language/reference.md b/docs/modules/expressive-language/reference.md index 07672302..fccdd69b 100644 --- a/docs/modules/expressive-language/reference.md +++ b/docs/modules/expressive-language/reference.md @@ -118,9 +118,9 @@ node, where the policy is actually attached to the run's `SteeringHandle`. ### `repl_agent` -Runs a host-provided script or model-driven CodeAct loop, bound by name to a -registered `Script` component. The node implementation is supplied by the host; -this crate ships no interpreter. +Runs a host-provided script node, bound by name to a registered `Script` +component. The node implementation is supplied by the host; this crate ships +no interpreter. Supported fields: From 6e33aadf3c81191858f1fc2ce2866c1ce533c40d Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Mon, 31 Aug 2026 21:36:28 +0300 Subject: [PATCH 07/25] chore: files changed CONTRIBUTING.md,docs/modules/expressive-language/README.md Auto-committed-on: dragonfly Co-authored-by: Medulla --- CONTRIBUTING.md | 24 ++++++++++++---------- docs/modules/expressive-language/README.md | 9 ++++---- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 710a526e..9973d515 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,23 +9,25 @@ Install a stable Rust toolchain with Rust 2024 support, then run: ```sh cargo fmt --check -cargo clippy --all-targets -- -D warnings -cargo build --all-targets -cargo test +cargo clippy --workspace --all-targets -- -D warnings +cargo build --workspace --all-targets +cargo test --workspace ``` The bundled example should also run: ```sh -cargo run --example basic_graph +cargo run -p tinyagents-integration-tests --example basic_graph ``` -To build with the optional embedded SQLite checkpointer or the `.ragsh` Rhai -session runtime, enable the relevant feature: +Cargo features are package-local. `tinyagents-harness` exposes `sqlite`, +`tools`, `multimodal`, and `tracing`; `tinyagents-graph` exposes `sqlite` and +`tracing`; `tinyagents-registry` and `tinyagents-session` expose `tracing`. +To build with a feature enabled, pass it on the relevant package: ```sh -cargo test --features sqlite -cargo test --features repl +cargo test -p tinyagents-harness --features sqlite +cargo test -p tinyagents-integration-tests --features sqlite ``` ### Submodules @@ -74,9 +76,9 @@ module-local unit tests in `test.rs`. Integration tests belong in `tests/`. Before opening a pull request: - run `cargo fmt --check` -- run `cargo clippy --all-targets -- -D warnings` -- run `cargo build --all-targets` -- run `cargo test` +- run `cargo clippy --workspace --all-targets -- -D warnings` +- run `cargo build --workspace --all-targets` +- run `cargo test --workspace` - add or update tests for behavior changes - update docs when public APIs, architecture, or examples change - keep the PR focused on one logical change diff --git a/docs/modules/expressive-language/README.md b/docs/modules/expressive-language/README.md index 0ea8ed5d..47d7a05d 100644 --- a/docs/modules/expressive-language/README.md +++ b/docs/modules/expressive-language/README.md @@ -15,11 +15,10 @@ become registry binding, policy checks, and graph compiler as a human-authored file. Generated topology must never be installed directly into the runtime. -This module is intentionally declarative. Interactive scripting and -CodeAct-style recursive execution are host concerns and are not implemented in -this crate. A `.rag` file defines graph topology and bindings; a host session -inspects, scripts, and orchestrates harness or graph calls through -capability-bound functions of its own. +This module is intentionally declarative. Interactive scripting is a host +concern and is not implemented in this crate. A `.rag` file defines graph +topology and bindings; a host session inspects, scripts, and orchestrates +harness or graph calls through capability-bound functions of its own. For what the parser/compiler implement today versus what is still aspirational, see [Implementation status](implementation-status.md). From 7ac72b75f04375598c12956fc66874333f881994 Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Mon, 31 Aug 2026 21:36:35 +0300 Subject: [PATCH 08/25] chore: files changed docs/modules/expressive-language/README.md Auto-committed-on: dragonfly Co-authored-by: Medulla --- docs/modules/expressive-language/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/modules/expressive-language/README.md b/docs/modules/expressive-language/README.md index 47d7a05d..5a8c4876 100644 --- a/docs/modules/expressive-language/README.md +++ b/docs/modules/expressive-language/README.md @@ -110,8 +110,7 @@ The docs can still describe the language as TinyAgents source. ## Expressiveness Targets The long-term language should cover the graph concepts proven useful in -LangGraph, LangChain agent graphs, OpenHuman's state-machine harness, and CodeAct -style orchestration: +LangGraph, LangChain agent graphs, and OpenHuman's state-machine harness: - graph defaults: recursion limits, timeouts, checkpointing, durability, streaming modes, cache policy, steering policy, and concurrency From a12b051bafc26a6a82f511ca30de2aa705258e01 Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Mon, 31 Aug 2026 21:36:40 +0300 Subject: [PATCH 09/25] chore: files changed SECURITY.md Auto-committed-on: dragonfly Co-authored-by: Medulla --- SECURITY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SECURITY.md b/SECURITY.md index caa0863f..08f6d8ea 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -31,7 +31,7 @@ before publishing details. Examples of in-scope issues: -- generated `.rag` or `.ragsh` source bypassing registry or policy checks +- generated `.rag` source bypassing registry or policy checks - unintended tool, model, store, or filesystem access - unsafe handling of credentials or secrets - prompt/context leakage across runs, forks, or sub-agents From 09d9d4d9355f8c2b7bdee79c0c6e2178ecc5ef53 Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Mon, 31 Aug 2026 21:36:53 +0300 Subject: [PATCH 10/25] chore: files changed SECURITY.md Auto-committed-on: dragonfly Co-authored-by: Medulla --- SECURITY.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index 08f6d8ea..2dfdc524 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -9,8 +9,8 @@ Report concerns to `contact@tinyhumans.ai`. ## Supported Versions -TinyAgents is pre-1.0. Security fixes target the `main` branch until the project -starts maintaining release branches. +Security fixes target the `main` branch until the project starts maintaining +release branches. ## Reporting A Vulnerability From 3b1475aa55efe74a32fc4036ea8c1f946f139661 Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Mon, 31 Aug 2026 21:37:05 +0300 Subject: [PATCH 11/25] chore: files changed ROADMAP.md Auto-committed-on: dragonfly Co-authored-by: Medulla --- ROADMAP.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ROADMAP.md b/ROADMAP.md index d48fcdb0..4acfdd9c 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,6 +1,6 @@ # Roadmap -TinyAgents is at v1.5.0. The roadmap favors small, well-tested modules that +TinyAgents is at v2.1.2. The roadmap favors small, well-tested modules that build toward a production-grade Rust agent runtime. ## Shipped Foundation From 559a417b3a7d9b1a19b82d31ee20ec34e4a562ca Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Mon, 31 Aug 2026 21:37:15 +0300 Subject: [PATCH 12/25] chore: files changed ROADMAP.md Auto-committed-on: dragonfly Co-authored-by: Medulla --- ROADMAP.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 4acfdd9c..79a9bbb6 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -17,15 +17,12 @@ build toward a production-grade Rust agent runtime. middleware, policy) bound by name (`registry/`) - the declarative `.rag` blueprint language: lexer, parser, compiler, and registry-backed binding (`language/`) -- the imperative `.ragsh` REPL language for capability-bound interactive - orchestration (`repl/`) -- an optional SQLite-backed checkpointer (`sqlite` feature) and an optional - Rhai-backed `.ragsh` session runtime (`repl` feature) +- an optional SQLite-backed checkpointer (`sqlite` feature) - an embedded Langfuse client and graph exporter for observability ## Near-Term Work -- broaden `.rag`/`.ragsh` example coverage for less-common routing and +- broaden `.rag` example coverage for less-common routing and parallel-fanout shapes - continue splitting any module or doc that grows past the 500-line limit into focused files From e500aa16b4c093fd7b93dc539e051b923d814515 Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Mon, 31 Aug 2026 21:37:41 +0300 Subject: [PATCH 13/25] chore: files changed docs/modules/harness/local-models.md Auto-committed-on: dragonfly Co-authored-by: Medulla --- docs/modules/harness/local-models.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/modules/harness/local-models.md b/docs/modules/harness/local-models.md index 9bf26e3f..9987fcbb 100644 --- a/docs/modules/harness/local-models.md +++ b/docs/modules/harness/local-models.md @@ -8,8 +8,9 @@ that works in development and stalls in production. This page documents what actually differs, what the crate already handles, and what a caller still has to configure. Everything here is asserted by -[`tests/live_local_models.rs`](../../../tests/live_local_models.rs) and -[`tests/live_local_embeddings.rs`](../../../tests/live_local_embeddings.rs) +[`tests/live_local_models.rs`](../../../crates/tinyagents-integration-tests/tests/live_local_models.rs) +and +[`tests/live_local_embeddings.rs`](../../../crates/tinyagents-integration-tests/tests/live_local_embeddings.rs) against real servers. ## Presets From 394daf9b1c41e81b94d2219620da2d7319624e76 Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Mon, 31 Aug 2026 21:38:02 +0300 Subject: [PATCH 14/25] chore: files changed AGENTS.md,CLAUDE.md Auto-committed-on: dragonfly Co-authored-by: Medulla --- AGENTS.md | 3 -- CLAUDE.md | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 99 insertions(+), 4 deletions(-) mode change 120000 => 100644 CLAUDE.md diff --git a/AGENTS.md b/AGENTS.md index 76ec837f..c7a519c7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,9 +11,6 @@ declarative `.rag` blueprint format), `crates/tinyagents-registry/` (the named capability catalog), and `crates/tinyagents-session/` (durable session data). `crates/tinyagents-tracing/` supplies shared opt-in tracing macros, while `crates/tinyagents-integration-tests/` owns cross-crate tests and examples. -Scripted, interpreter-backed orchestration (a CodeAct/REPL loop) is a host -concern and is deliberately not implemented here. - Prefer small, focused modules that do one thing extremely well. New feature areas should live in module directories instead of accumulating broad, multi-purpose files. Within each module directory, keep type definitions in a diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 120000 index 47dc3e3d..00000000 --- a/CLAUDE.md +++ /dev/null @@ -1 +0,0 @@ -AGENTS.md \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..c7a519c7 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,99 @@ +# Repository Guidelines + +## Project Structure & Module Organization + +TinyAgents is a Rust 2024 virtual workspace rooted at `Cargo.toml`. It has no +compatibility facade crate: consumers depend directly on the focused package +that owns an API. The public packages are `crates/tinyagents-graph/` (durable +typed state graphs), `crates/tinyagents-harness/` (provider-neutral model +calls, tools, middleware, and streaming), `crates/tinyagents-language/` (the +declarative `.rag` blueprint format), `crates/tinyagents-registry/` (the named +capability catalog), and `crates/tinyagents-session/` (durable session data). +`crates/tinyagents-tracing/` supplies shared opt-in tracing macros, while +`crates/tinyagents-integration-tests/` owns cross-crate tests and examples. +Prefer small, focused modules that do one thing extremely well. New feature +areas should live in module directories instead of accumulating broad, +multi-purpose files. Within each module directory, keep type definitions in a +dedicated `types.rs` file and keep module-local unit tests in a dedicated +`test.rs` file. The module root should wire the pieces together and expose the +smallest useful API. + +Cargo features are package-local. `tinyagents-harness` exposes `sqlite`, +`tools`, `multimodal`, and `tracing`; `tinyagents-graph` exposes `sqlite` and +`tracing`; registry and session expose `tracing`. Tracing instrumentation is +compiled out by default. + +Integration tests are in `crates/tinyagents-integration-tests/tests/`, covering serialization, graph routing, +registry binding, the expressive language, streaming, subagents, +and provider contracts (including live, network-gated tests such as +`tests/live_*.rs`). Runnable usage examples are in +`crates/tinyagents-integration-tests/examples/`, especially `basic_graph.rs`. +Design notes and module-level specifications live +in `docs/`, with `docs/spec/README.md` as the top-level architecture +reference and `docs/modules/` holding per-surface design docs (`graph/`, +`harness/`, `registry/`, `expressive-language/`). A `wiki/` +git submodule holds the published GitHub wiki pages; do not edit it as part +of unrelated work, and commit its pointer update separately when it does +change. + +## Build, Test, and Development Commands + +- `cargo fmt --check`: verify Rust formatting without changing files. +- `cargo fmt`: format the crate before committing. +- `cargo clippy --workspace --all-targets -- -D warnings`: run lint checks for the libraries, + tests, and examples, treating warnings as failures. +- `cargo build --workspace --all-targets`: compile all crate targets. +- `cargo test --workspace`: run the full test suite. +- `cargo run -p tinyagents-integration-tests --example basic_graph`: run the bundled graph execution example. + +Run commands from the repository root unless a future workspace layout changes +the crate location. + +## Coding Style & Naming Conventions + +Use standard `rustfmt` output and Rust 2024 idioms. Module and file names should +be `snake_case`; public types and traits should be `PascalCase`; functions, +methods, fields, and local variables should be `snake_case`. Prefer small, +typed APIs with `Result` using `tinyagents_harness::TinyAgentsError`. Keep +public exports centralized in each package's `src/lib.rs` so downstream users +have a predictable surface. + +## Testing Guidelines + +Place integration tests in `crates/tinyagents-integration-tests/tests/` and use descriptive test names such as +`serializes_chat_messages`. Add focused tests when changing serialization, +graph routing, tool invocation, or public model request/response shapes. For +async behavior, use the existing `tokio` dev dependency rather than introducing +another runtime. + +Maintain at least 80% test coverage for meaningful library behavior. Add or +update tests with every behavior change, and document any intentionally +untested edge case in the PR description. + +## Documentation Expectations + +Write thorough documentation for public APIs, architecture decisions, examples, +and non-obvious behavior. Keep `README.md`, `docs/spec/README.md`, and module +docs in `docs/modules/` aligned with code changes. Prefer concrete examples +over vague descriptions, especially for graph execution, model abstractions, +and tool integration. + +Keep every Markdown file, including `AGENTS.md`, at 500 lines or fewer. When a +topic grows past that limit, split it into focused files and link them from the +module's `README.md`. Complex modules must always include a module-level +`README.md` that explains the design, public surface, and important operational +constraints. + +## Commit & Pull Request Guidelines + +Recent history uses concise, imperative commit subjects such as +`Enhance SPEC.md with detailed descriptions...` and `Initial implementation...`. +Keep the first line specific to the change and avoid bundling unrelated work. + +Pull requests should include a short summary, the commands run locally, and any +API or behavior changes. Link related issues when available. Include updated +examples or docs when public APIs, architecture, or expected usage changes. + +Always make small, focused commits. Each commit should cover one logical change, +build independently, and avoid mixing formatting, refactors, and behavior +changes unless they are inseparable. From ef19bcaf3b18aea42411384ea7aa8097a34052db Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Mon, 31 Aug 2026 21:38:06 +0300 Subject: [PATCH 15/25] chore: files changed AGENTS.md,CLAUDE.md Auto-committed-on: dragonfly Co-authored-by: Medulla --- AGENTS.md | 1 + CLAUDE.md | 1 + 2 files changed, 2 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index c7a519c7..927e1d8b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,6 +11,7 @@ declarative `.rag` blueprint format), `crates/tinyagents-registry/` (the named capability catalog), and `crates/tinyagents-session/` (durable session data). `crates/tinyagents-tracing/` supplies shared opt-in tracing macros, while `crates/tinyagents-integration-tests/` owns cross-crate tests and examples. + Prefer small, focused modules that do one thing extremely well. New feature areas should live in module directories instead of accumulating broad, multi-purpose files. Within each module directory, keep type definitions in a diff --git a/CLAUDE.md b/CLAUDE.md index c7a519c7..927e1d8b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -11,6 +11,7 @@ declarative `.rag` blueprint format), `crates/tinyagents-registry/` (the named capability catalog), and `crates/tinyagents-session/` (durable session data). `crates/tinyagents-tracing/` supplies shared opt-in tracing macros, while `crates/tinyagents-integration-tests/` owns cross-crate tests and examples. + Prefer small, focused modules that do one thing extremely well. New feature areas should live in module directories instead of accumulating broad, multi-purpose files. Within each module directory, keep type definitions in a From cbb9929e1df55c97e6a96ba7a482badcc40734c4 Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Mon, 31 Aug 2026 21:47:08 +0300 Subject: [PATCH 16/25] chore: files changed wiki Auto-committed-on: dragonfly Co-authored-by: Medulla --- wiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wiki b/wiki index b02f5826..5b8f5927 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit b02f58269a4fc8742571f92e191ec893e9890eb0 +Subproject commit 5b8f5927caa2ba0730985e686bf5ef5550e53e6d From 021d2a4e67e2d619ce1a04f90ee19f329e04857f Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Mon, 31 Aug 2026 21:48:12 +0300 Subject: [PATCH 17/25] fix: restore CLAUDE.md symlink to AGENTS.md Co-authored-by: Medulla --- CLAUDE.md | 101 +----------------------------------------------------- 1 file changed, 1 insertion(+), 100 deletions(-) mode change 100644 => 120000 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 927e1d8b..00000000 --- a/CLAUDE.md +++ /dev/null @@ -1,100 +0,0 @@ -# Repository Guidelines - -## Project Structure & Module Organization - -TinyAgents is a Rust 2024 virtual workspace rooted at `Cargo.toml`. It has no -compatibility facade crate: consumers depend directly on the focused package -that owns an API. The public packages are `crates/tinyagents-graph/` (durable -typed state graphs), `crates/tinyagents-harness/` (provider-neutral model -calls, tools, middleware, and streaming), `crates/tinyagents-language/` (the -declarative `.rag` blueprint format), `crates/tinyagents-registry/` (the named -capability catalog), and `crates/tinyagents-session/` (durable session data). -`crates/tinyagents-tracing/` supplies shared opt-in tracing macros, while -`crates/tinyagents-integration-tests/` owns cross-crate tests and examples. - -Prefer small, focused modules that do one thing extremely well. New feature -areas should live in module directories instead of accumulating broad, -multi-purpose files. Within each module directory, keep type definitions in a -dedicated `types.rs` file and keep module-local unit tests in a dedicated -`test.rs` file. The module root should wire the pieces together and expose the -smallest useful API. - -Cargo features are package-local. `tinyagents-harness` exposes `sqlite`, -`tools`, `multimodal`, and `tracing`; `tinyagents-graph` exposes `sqlite` and -`tracing`; registry and session expose `tracing`. Tracing instrumentation is -compiled out by default. - -Integration tests are in `crates/tinyagents-integration-tests/tests/`, covering serialization, graph routing, -registry binding, the expressive language, streaming, subagents, -and provider contracts (including live, network-gated tests such as -`tests/live_*.rs`). Runnable usage examples are in -`crates/tinyagents-integration-tests/examples/`, especially `basic_graph.rs`. -Design notes and module-level specifications live -in `docs/`, with `docs/spec/README.md` as the top-level architecture -reference and `docs/modules/` holding per-surface design docs (`graph/`, -`harness/`, `registry/`, `expressive-language/`). A `wiki/` -git submodule holds the published GitHub wiki pages; do not edit it as part -of unrelated work, and commit its pointer update separately when it does -change. - -## Build, Test, and Development Commands - -- `cargo fmt --check`: verify Rust formatting without changing files. -- `cargo fmt`: format the crate before committing. -- `cargo clippy --workspace --all-targets -- -D warnings`: run lint checks for the libraries, - tests, and examples, treating warnings as failures. -- `cargo build --workspace --all-targets`: compile all crate targets. -- `cargo test --workspace`: run the full test suite. -- `cargo run -p tinyagents-integration-tests --example basic_graph`: run the bundled graph execution example. - -Run commands from the repository root unless a future workspace layout changes -the crate location. - -## Coding Style & Naming Conventions - -Use standard `rustfmt` output and Rust 2024 idioms. Module and file names should -be `snake_case`; public types and traits should be `PascalCase`; functions, -methods, fields, and local variables should be `snake_case`. Prefer small, -typed APIs with `Result` using `tinyagents_harness::TinyAgentsError`. Keep -public exports centralized in each package's `src/lib.rs` so downstream users -have a predictable surface. - -## Testing Guidelines - -Place integration tests in `crates/tinyagents-integration-tests/tests/` and use descriptive test names such as -`serializes_chat_messages`. Add focused tests when changing serialization, -graph routing, tool invocation, or public model request/response shapes. For -async behavior, use the existing `tokio` dev dependency rather than introducing -another runtime. - -Maintain at least 80% test coverage for meaningful library behavior. Add or -update tests with every behavior change, and document any intentionally -untested edge case in the PR description. - -## Documentation Expectations - -Write thorough documentation for public APIs, architecture decisions, examples, -and non-obvious behavior. Keep `README.md`, `docs/spec/README.md`, and module -docs in `docs/modules/` aligned with code changes. Prefer concrete examples -over vague descriptions, especially for graph execution, model abstractions, -and tool integration. - -Keep every Markdown file, including `AGENTS.md`, at 500 lines or fewer. When a -topic grows past that limit, split it into focused files and link them from the -module's `README.md`. Complex modules must always include a module-level -`README.md` that explains the design, public surface, and important operational -constraints. - -## Commit & Pull Request Guidelines - -Recent history uses concise, imperative commit subjects such as -`Enhance SPEC.md with detailed descriptions...` and `Initial implementation...`. -Keep the first line specific to the change and avoid bundling unrelated work. - -Pull requests should include a short summary, the commands run locally, and any -API or behavior changes. Link related issues when available. Include updated -examples or docs when public APIs, architecture, or expected usage changes. - -Always make small, focused commits. Each commit should cover one logical change, -build independently, and avoid mixing formatting, refactors, and behavior -changes unless they are inseparable. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 00000000..47dc3e3d --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file From 161abcbd681c9c3d9ff7b35b2352cf20b8b692ee Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Mon, 31 Aug 2026 21:48:48 +0300 Subject: [PATCH 18/25] chore: files changed crates/tinyagents-integration-tests/examples/_readme_check.rs Auto-committed-on: dragonfly Co-authored-by: Medulla --- .../examples/_readme_check.rs | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 crates/tinyagents-integration-tests/examples/_readme_check.rs diff --git a/crates/tinyagents-integration-tests/examples/_readme_check.rs b/crates/tinyagents-integration-tests/examples/_readme_check.rs new file mode 100644 index 00000000..c1cae93e --- /dev/null +++ b/crates/tinyagents-integration-tests/examples/_readme_check.rs @@ -0,0 +1,51 @@ +use std::sync::Arc; +use tinyagents_graph::*; +use tinyagents_harness::runtime::AgentHarness; +use tinyinference::message::Message; +use tinyinference::providers::openai::OpenAiModel; + +#[derive(Clone, Debug)] +struct AgentState { + messages: Vec, + needs_tool: bool, +} + +#[allow(dead_code)] +async fn graph_snippet() -> Result<(), Box> { + let graph = GraphBuilder::::overwrite() + .add_node("agent", |mut state: AgentState, _ctx: NodeContext| async move { + state.messages.push(Message::assistant("checking the local tool")); + Ok(NodeResult::Update(state)) + }) + .add_node("tool", |mut state: AgentState, _ctx: NodeContext| async move { + state.messages.push(Message::tool("echo", "tool result")); + state.needs_tool = false; + Ok(NodeResult::Update(state)) + }) + .set_entry("agent") + .add_conditional_edges( + "agent", + |state: &AgentState| if state.needs_tool { "tool".to_string() } else { "done".to_string() }, + [("tool", "tool"), ("done", END)], + ) + .add_edge("tool", "agent") + .compile()?; + + let _run = graph.run(AgentState { messages: vec![], needs_tool: true }).await?; + Ok(()) +} + +#[allow(dead_code)] +async fn harness_snippet() -> Result<(), Box> { + let model = OpenAiModel::from_env()?; + let mut harness: AgentHarness<()> = AgentHarness::new(); + harness.register_model("openai", Arc::new(model)).set_default_model("openai"); + + let run = harness + .invoke_default(&(), vec![Message::user("What is a Rust trait?")]) + .await?; + println!("{}", run.text().unwrap_or_default()); + Ok(()) +} + +fn main() {} From 90f5a75040f1d86733ee9e85f89e0e46838a0d9b Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Mon, 31 Aug 2026 21:48:57 +0300 Subject: [PATCH 19/25] chore: files changed crates/tinyagents-integration-tests/examples/_readme_check.rs Auto-committed-on: dragonfly Co-authored-by: Medulla --- crates/tinyagents-integration-tests/examples/_readme_check.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/tinyagents-integration-tests/examples/_readme_check.rs b/crates/tinyagents-integration-tests/examples/_readme_check.rs index c1cae93e..de10516d 100644 --- a/crates/tinyagents-integration-tests/examples/_readme_check.rs +++ b/crates/tinyagents-integration-tests/examples/_readme_check.rs @@ -11,7 +11,7 @@ struct AgentState { } #[allow(dead_code)] -async fn graph_snippet() -> Result<(), Box> { +async fn graph_snippet() -> std::result::Result<(), Box> { let graph = GraphBuilder::::overwrite() .add_node("agent", |mut state: AgentState, _ctx: NodeContext| async move { state.messages.push(Message::assistant("checking the local tool")); @@ -36,7 +36,7 @@ async fn graph_snippet() -> Result<(), Box> { } #[allow(dead_code)] -async fn harness_snippet() -> Result<(), Box> { +async fn harness_snippet() -> std::result::Result<(), Box> { let model = OpenAiModel::from_env()?; let mut harness: AgentHarness<()> = AgentHarness::new(); harness.register_model("openai", Arc::new(model)).set_default_model("openai"); From d25a78e90a32d3cbbac6d1b6dde5548bdb2692f6 Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Mon, 31 Aug 2026 21:49:07 +0300 Subject: [PATCH 20/25] chore: files changed README.md,crates/tinyagents-integration-tests/examples/_readme_check.rs Auto-committed-on: dragonfly Co-authored-by: Medulla --- README.md | 6 +-- .../examples/_readme_check.rs | 51 ------------------- 2 files changed, 2 insertions(+), 55 deletions(-) delete mode 100644 crates/tinyagents-integration-tests/examples/_readme_check.rs diff --git a/README.md b/README.md index 7e608a57..bea4e080 100644 --- a/README.md +++ b/README.md @@ -45,12 +45,10 @@ TinyAgents is a Cargo workspace, not one crate. Depend on the pieces you need: - **`tinyagents-integration-tests`** — cross-crate tests and the runnable examples referenced below (not published, workspace-internal). -None of the crates are published to crates.io (`publish = false` in every -`Cargo.toml`); use path or git dependencies. - ## Quick start -None of the crates ship on crates.io, so add them as git or path dependencies: +None of the crates are published to crates.io (`publish = false` in every +`Cargo.toml`), so add them as git or path dependencies: ```toml [dependencies] diff --git a/crates/tinyagents-integration-tests/examples/_readme_check.rs b/crates/tinyagents-integration-tests/examples/_readme_check.rs deleted file mode 100644 index de10516d..00000000 --- a/crates/tinyagents-integration-tests/examples/_readme_check.rs +++ /dev/null @@ -1,51 +0,0 @@ -use std::sync::Arc; -use tinyagents_graph::*; -use tinyagents_harness::runtime::AgentHarness; -use tinyinference::message::Message; -use tinyinference::providers::openai::OpenAiModel; - -#[derive(Clone, Debug)] -struct AgentState { - messages: Vec, - needs_tool: bool, -} - -#[allow(dead_code)] -async fn graph_snippet() -> std::result::Result<(), Box> { - let graph = GraphBuilder::::overwrite() - .add_node("agent", |mut state: AgentState, _ctx: NodeContext| async move { - state.messages.push(Message::assistant("checking the local tool")); - Ok(NodeResult::Update(state)) - }) - .add_node("tool", |mut state: AgentState, _ctx: NodeContext| async move { - state.messages.push(Message::tool("echo", "tool result")); - state.needs_tool = false; - Ok(NodeResult::Update(state)) - }) - .set_entry("agent") - .add_conditional_edges( - "agent", - |state: &AgentState| if state.needs_tool { "tool".to_string() } else { "done".to_string() }, - [("tool", "tool"), ("done", END)], - ) - .add_edge("tool", "agent") - .compile()?; - - let _run = graph.run(AgentState { messages: vec![], needs_tool: true }).await?; - Ok(()) -} - -#[allow(dead_code)] -async fn harness_snippet() -> std::result::Result<(), Box> { - let model = OpenAiModel::from_env()?; - let mut harness: AgentHarness<()> = AgentHarness::new(); - harness.register_model("openai", Arc::new(model)).set_default_model("openai"); - - let run = harness - .invoke_default(&(), vec![Message::user("What is a Rust trait?")]) - .await?; - println!("{}", run.text().unwrap_or_default()); - Ok(()) -} - -fn main() {} From f537bc814f6178bdc70976d9c2f5e09393f50d8b Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Mon, 31 Aug 2026 22:01:41 +0300 Subject: [PATCH 21/25] chore: files changed vendor/tinyinference Auto-committed-on: dragonfly Co-authored-by: Medulla --- vendor/tinyinference | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/tinyinference b/vendor/tinyinference index 70412ce5..d2e377ae 160000 --- a/vendor/tinyinference +++ b/vendor/tinyinference @@ -1 +1 @@ -Subproject commit 70412ce59215ac73d61385cf782603e9c046e004 +Subproject commit d2e377ae19a6d27785927f4564526653ae8a8906 From 0d549d9dba6c05ad467d5b4b197ac594bd96108d Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Mon, 31 Aug 2026 22:02:21 +0300 Subject: [PATCH 22/25] chore: files changed .gitmodules Auto-committed-on: dragonfly Co-authored-by: Medulla --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index e1d1d544..d8a9c977 100644 --- a/.gitmodules +++ b/.gitmodules @@ -6,4 +6,4 @@ url = https://github.com/tinyhumansai/tinytools.git [submodule "vendor/tinyinference"] path = vendor/tinyinference - url = git@github.com:tinyhumansai/tinyinference.git + url = https://github.com/tinyhumansai/tinyinference.git From 4d43f2cf3afd6beb0b5f95b7bd187ad84e3c2449 Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Mon, 31 Aug 2026 22:02:50 +0300 Subject: [PATCH 23/25] docs(readme): add tinyinference dependency to setup example Document that the code samples require a separate tinyinference git dependency, since the message and provider types are not re-exported by the crates listed above. Auto-committed-on: dragonfly Co-authored-by: Medulla --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index bea4e080..33b6dadb 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,10 @@ tinyagents-harness = { git = "https://github.com/tinyhumansai/tinyagents", packa tinyagents-graph = { git = "https://github.com/tinyhumansai/tinyagents", package = "tinyagents-graph" } tinyagents-language = { git = "https://github.com/tinyhumansai/tinyagents", package = "tinyagents-language" } tinyagents-registry = { git = "https://github.com/tinyhumansai/tinyagents", package = "tinyagents-registry" } +# The code samples below build `Message` and provider types directly from +# TinyInference, the message/model crate TinyAgents is built on. It is a +# separate git dependency, not re-exported by the crates above. +tinyinference = { git = "https://github.com/tinyhumansai/tinyinference", package = "tinyinference" } ``` A minimal typed graph — a whole-state agent/tool loop (trimmed from From 6462f6f8fa7735f71f25dff0a5e4957e6738c001 Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Mon, 31 Aug 2026 22:06:01 +0300 Subject: [PATCH 24/25] chore: files changed crates/tinyagents-integration-tests/examples/_readme_check.rs Auto-committed-on: dragonfly Co-authored-by: Medulla --- .../examples/_readme_check.rs | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 crates/tinyagents-integration-tests/examples/_readme_check.rs diff --git a/crates/tinyagents-integration-tests/examples/_readme_check.rs b/crates/tinyagents-integration-tests/examples/_readme_check.rs new file mode 100644 index 00000000..f747fe32 --- /dev/null +++ b/crates/tinyagents-integration-tests/examples/_readme_check.rs @@ -0,0 +1,67 @@ +use std::sync::Arc; +use tinyagents_graph::*; +use tinyagents_harness::runtime::AgentHarness; +use tinyinference::message::Message; +use tinyinference::providers::openai::OpenAiModel; + +#[derive(Clone, Debug)] +struct AgentState { + messages: Vec, + needs_tool: bool, +} + +#[tokio::main] +async fn main() -> tinyagents_harness::error::Result<()> { + let graph = GraphBuilder::::overwrite() + .add_node( + "agent", + |mut state: AgentState, _ctx: NodeContext| async move { + state + .messages + .push(Message::assistant("checking the local tool")); + Ok(NodeResult::Update(state)) + }, + ) + .add_node( + "tool", + |mut state: AgentState, _ctx: NodeContext| async move { + state.messages.push(Message::tool("echo", "tool result")); + state.needs_tool = false; + Ok(NodeResult::Update(state)) + }, + ) + .set_entry("agent") + .add_conditional_edges( + "agent", + |state: &AgentState| { + if state.needs_tool { + "tool".to_string() + } else { + "done".to_string() + } + }, + [("tool", "tool"), ("done", END)], + ) + .add_edge("tool", "agent") + .compile()?; + + let _run = graph + .run(AgentState { + messages: vec![], + needs_tool: true, + }) + .await?; + + let model = OpenAiModel::from_env()?; + let mut harness: AgentHarness<()> = AgentHarness::new(); + harness + .register_model("openai", Arc::new(model)) + .set_default_model("openai"); + + let run = harness + .invoke_default(&(), vec![Message::user("What is a Rust trait?")]) + .await?; + println!("{}", run.text().unwrap_or_default()); + + Ok(()) +} From 68c007cf2280a2f35426fe9145b0bea71418c234 Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Mon, 31 Aug 2026 22:06:18 +0300 Subject: [PATCH 25/25] chore: files changed crates/tinyagents-integration-tests/examples/_readme_check.rs Auto-committed-on: dragonfly Co-authored-by: Medulla --- .../examples/_readme_check.rs | 67 ------------------- 1 file changed, 67 deletions(-) delete mode 100644 crates/tinyagents-integration-tests/examples/_readme_check.rs diff --git a/crates/tinyagents-integration-tests/examples/_readme_check.rs b/crates/tinyagents-integration-tests/examples/_readme_check.rs deleted file mode 100644 index f747fe32..00000000 --- a/crates/tinyagents-integration-tests/examples/_readme_check.rs +++ /dev/null @@ -1,67 +0,0 @@ -use std::sync::Arc; -use tinyagents_graph::*; -use tinyagents_harness::runtime::AgentHarness; -use tinyinference::message::Message; -use tinyinference::providers::openai::OpenAiModel; - -#[derive(Clone, Debug)] -struct AgentState { - messages: Vec, - needs_tool: bool, -} - -#[tokio::main] -async fn main() -> tinyagents_harness::error::Result<()> { - let graph = GraphBuilder::::overwrite() - .add_node( - "agent", - |mut state: AgentState, _ctx: NodeContext| async move { - state - .messages - .push(Message::assistant("checking the local tool")); - Ok(NodeResult::Update(state)) - }, - ) - .add_node( - "tool", - |mut state: AgentState, _ctx: NodeContext| async move { - state.messages.push(Message::tool("echo", "tool result")); - state.needs_tool = false; - Ok(NodeResult::Update(state)) - }, - ) - .set_entry("agent") - .add_conditional_edges( - "agent", - |state: &AgentState| { - if state.needs_tool { - "tool".to_string() - } else { - "done".to_string() - } - }, - [("tool", "tool"), ("done", END)], - ) - .add_edge("tool", "agent") - .compile()?; - - let _run = graph - .run(AgentState { - messages: vec![], - needs_tool: true, - }) - .await?; - - let model = OpenAiModel::from_env()?; - let mut harness: AgentHarness<()> = AgentHarness::new(); - harness - .register_model("openai", Arc::new(model)) - .set_default_model("openai"); - - let run = harness - .invoke_default(&(), vec![Message::user("What is a Rust trait?")]) - .await?; - println!("{}", run.text().unwrap_or_default()); - - Ok(()) -}