-
Notifications
You must be signed in to change notification settings - Fork 15
Development
This is the contributor and local-development guide for TinyAgents. The workspace is deliberately split into small crates, and the code inside each crate is organized into small, inspectable modules. This page covers the toolchain, the canonical commands, the repo layout, and the testing and documentation expectations every change is held to.
-
Rust 2024 edition. Install a stable Rust toolchain new enough to support
the 2024 edition (
rustup update stable). No nightly features are required. - The repository is a virtual Cargo workspace rooted at
Cargo.toml, with members undercrates/*. There is no facade crate — see Quick Start for the crate list. - The default build is offline:
tinyagents-harnessdepends unconditionally on the OpenAI-compatible adapter in the vendoredtinyinferencecrate, but it makes no network call unless invoked, and tests that would call it skip without a key (see Live / provider tests). - Optional Cargo features are per-crate, off by default:
-
tinyagents-harness:sqlite(SQLite-backed response cache),tools(built-in tool implementations),multimodal(image/data-URI handling),tracing. -
tinyagents-graph:sqlite(SqliteCheckpointer),tracing. -
tinyagents-registry,tinyagents-session:tracing. -
tinyagents-language: no optional features.
-
Run these from the repository root. They mirror the CI gate — every one must pass before a change is ready for review.
cargo fmt --check # verify formatting (no changes)
cargo clippy --workspace --all-targets -- -D warnings # lint lib + tests + examples, warnings = errors
cargo build --workspace --all-targets # compile every target
cargo test --workspace # run the full suite (offline)
cargo run -p tinyagents-integration-tests --example basic_graph # run the bundled graph exampleUse cargo fmt (without --check) to apply formatting before committing.
Always format with stock rustfmt; do not hand-tune layout.
To additionally compile the optional backends, pass --features to the crate
that owns the feature, or use --all-features for a specific package:
cargo test -p tinyagents-graph --features sqlite
cargo test -p tinyagents-harness --all-featuresTests that would make real network calls are guarded (see below), so
cargo test --workspace stays green without credentials.
Public API exports are centralized in each crate's src/lib.rs so downstream
users have one predictable surface per crate.
Cargo.toml workspace manifest
crates/tinyagents-harness/ provider-neutral model calls, tools,
middleware, streaming, sub-agents
crates/tinyagents-graph/ durable typed state-graph runtime (nodes,
edges, checkpoints, subgraphs)
crates/tinyagents-registry/ named capability catalog bound by .rag
crates/tinyagents-language/ the declarative .rag blueprint language
(lexer -> parser -> compiler)
crates/tinyagents-session/ durable SQLite-backed session history
crates/tinyagents-tracing/ shared, feature-gated tracing macros
crates/tinyagents-integration-tests/ cross-crate tests/ and examples/
docs/ design notes and module specs
wiki/ this developer-facing wiki
New feature areas live in module directories, not broad multi-purpose files. Within each module directory:
-
mod.rswires the pieces together and exposes the smallest useful API. -
types.rsholds the module's type definitions. -
test.rsholds module-local unit tests (declared#[cfg(test)] mod test;).
Prefer small modules that do one thing well. Public types and traits are
PascalCase; modules, files, functions, methods, fields, and locals are
snake_case. Prefer small, typed APIs returning each crate's Result<T>
over panics or stringly-typed errors.
Keep all of these aligned with code changes:
-
README.md— top-level overview and quick start. -
docs/spec/README.md— top-level architecture reference. -
docs/modules/— per-module design docs. Complex modules must include a module-levelREADME.mdexplaining design, public surface, and operational constraints. -
wiki/— developer-facing, example-rich guides (this page lives here). - In-source rustdoc (
//!module headers and///item docs).
Keep every Markdown file at 500 lines or fewer. When a topic outgrows
that, split it into focused files and link them from the module's
README.md.
- Cross-crate integration tests go in
crates/tinyagents-integration-tests/tests/, with descriptive names such asserializes_chat_messages. This is the only crate with atests/directory; the other crates keep their tests in module-localtest.rsfiles instead. - For async behavior, use the existing
tokiodev-dependency rather than introducing another runtime.futuresis available for driving streams anddotenvyfor example env loading. - 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.
- Add focused tests whenever you change serialization, graph routing, tool invocation, sub-agent/subgraph behavior, or public model request/response shapes.
Much of the suite leans on tinyinference::providers::MockModel — a
deterministic, network-free ChatModel with echo, constant,
with_responses, and with_tool_call constructors — so graph and harness
behavior can be tested without any provider.
Network-backed provider code is always compiled (see Providers); the tests below are opt-in and skip without credentials.
Copy providers.env.example to providers.env and fill in the keys you
have — a blank key means that provider is skipped:
cp providers.env.example providers.env
PROVIDER_MATRIX=1 cargo test -p tinyagents-integration-tests --test live_provider_matrix -- --nocaptureThis reports a chat call, a streaming call, and a tool call per configured
provider as a provider | PASS/FAIL(reason) | latency(ms) table. Dialling is
opt-in through PROVIDER_MATRIX=1, so a bare cargo test --workspace stays
offline even with a fully configured providers.env. providers.env is
gitignored — never commit real keys. See
vendor/tinyinference/crates/tinyinference/src/providers/openai/README.md
for the adapter's configuration format.
To run the OpenAI-backed examples directly, set OPENAI_API_KEY in the
environment or a .env file at the repo root (loaded via dotenvy):
export OPENAI_API_KEY=sk-...
cargo run -p tinyagents-integration-tests --example openai_chat
cargo run -p tinyagents-integration-tests --example openai_tools
cargo run -p tinyagents-integration-tests --example openai_structured
cargo run -p tinyagents-integration-tests --example openai_graph_agent
cargo run -p tinyagents-integration-tests --example openai_self_blueprintKeep tests that perform real network calls opt-in (env-gated) so the default
cargo test --workspace run stays offline and deterministic for every
contributor and for CI.
Before opening a PR (always against the upstream tinyhumansai/tinyagents
repository, not a fork):
cargo fmt --checkcargo clippy --workspace --all-targets -- -D warningscargo build --workspace --all-targetscargo test --workspace- add or update tests for behavior changes
- update
README.md,docs/, wiki, and rustdoc when public APIs, architecture, or expected usage change - keep the PR focused on one logical change
Use concise, imperative commit subjects (for example, Add graph route validation tests or Document expressive language safety boundary). Make
small, focused commits: each should cover one logical change, build
independently, and avoid mixing formatting, refactors, and behavior changes
unless they are inseparable.
- Providers — configuring model providers.
-
CONTRIBUTING.mdandAGENTS.md— the authoritative source for these conventions. -
docs/spec/README.md— the architecture reference.
Provider-neutral agent harness and durable state-graph runtime for Rust.
Getting started
Concepts
Modules
Providers
Contributing