Skip to content

Development

Steven Enamakel edited this page Aug 31, 2026 · 5 revisions

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.

Toolchain

  • 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 under crates/*. There is no facade crate — see Quick Start for the crate list.
  • The default build is offline: tinyagents-harness depends unconditionally on the OpenAI-compatible adapter in the vendored tinyinference crate, 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.

Canonical commands

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 example

Use 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-features

Tests that would make real network calls are guarded (see below), so cargo test --workspace stays green without credentials.

Repository layout

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

The module convention

New feature areas live in module directories, not broad multi-purpose files. Within each module directory:

  • mod.rs wires the pieces together and exposes the smallest useful API.
  • types.rs holds the module's type definitions.
  • test.rs holds 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.

Where documentation lives

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-level README.md explaining 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.

Testing and coverage expectations

  • Cross-crate integration tests go in crates/tinyagents-integration-tests/tests/, with descriptive names such as serializes_chat_messages. This is the only crate with a tests/ directory; the other crates keep their tests in module-local test.rs files instead.
  • For async behavior, use the existing tokio dev-dependency rather than introducing another runtime. futures is available for driving streams and dotenvy for 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.

Live / provider tests

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 -- --nocapture

This 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_blueprint

Keep 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.

Pull-request checklist

Before opening a PR (always against the upstream tinyhumansai/tinyagents repository, not a fork):

  • cargo fmt --check
  • cargo clippy --workspace --all-targets -- -D warnings
  • cargo build --workspace --all-targets
  • cargo 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

Commits

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.

See also

  • Providers — configuring model providers.
  • CONTRIBUTING.md and AGENTS.md — the authoritative source for these conventions.
  • docs/spec/README.md — the architecture reference.

TinyAgents

Provider-neutral agent harness and durable state-graph runtime for Rust.

Getting started

Concepts

Modules

Providers

Contributing


Clone this wiki locally