Skip to content

Latest commit

 

History

History
182 lines (128 loc) · 5.5 KB

File metadata and controls

182 lines (128 loc) · 5.5 KB

AGENTS.md

Operational instructions for AI coding agents working in Rig.

For contributor-facing policy, PR expectations, and accountability guidance, see CONTRIBUTING.md. This file is for repository-specific engineering rules that agents must follow while reading, editing, testing, and documenting code.

First Principles

  • Read the existing implementation before changing code.
  • Keep changes scoped to the user's request.
  • Prefer existing Rig traits, builders, modules, and error types over new abstractions.
  • Do not add TODOs, stubs, placeholder implementations, or speculative APIs.
  • Do not make commits, stage changes, push branches, or open PRs unless the user explicitly asks.
  • Do not discard user changes.

Repository Shape

  • Root facade crate: rig
  • Core crate: crates/rig-core
  • Companion provider and vector-store crates: crates/rig-*
  • Root examples: examples/
  • Per-crate examples: crates/<crate>/examples/
  • Provider-backed tests: tests/providers/ and provider-specific integration tests

The root rig crate re-exports rig-core and exposes companion crates behind feature flags. Check Cargo.toml before documenting or changing exposed features, integrations, or module paths.

Core Architecture

Rig is built around provider-agnostic traits:

  • CompletionModel for text completion and chat models
  • EmbeddingModel for embedding generation
  • VectorStoreIndex for vector similarity search
  • Tool for callable tools

Use these traits instead of creating parallel abstractions.

Configurable public types should follow Rig's builder style:

let agent = client
    .agent(openai::GPT_5_2)
    .preamble("System prompt")
    .tool(my_tool)
    .temperature(0.8)
    .build();

Provider clients use the generic client architecture:

pub struct Client<Ext = Nothing, H = reqwest::Client> {
    // ...
}

Providers declare capabilities explicitly with Capable<T> and Nothing.

WASM Compatibility

Rig supports WebAssembly targets.

Use WasmCompatSend and WasmCompatSync in trait bounds instead of raw Send and Sync.

Use WasmBoxedFuture for boxed futures.

When an error type stores boxed errors, use platform-specific bounds:

#[cfg(not(target_family = "wasm"))]
Box<dyn std::error::Error + Send + Sync + 'static>

#[cfg(target_family = "wasm")]
Box<dyn std::error::Error + 'static>

Error Handling

  • Do not use String as an error type for new fallible APIs.
  • Use explicit error enums with thiserror.
  • Do not use .unwrap() or .expect() on fallible operations unless the condition is genuinely impossible and obvious from the code.
  • Prefer ? and meaningful error conversions.

Documentation

  • Add /// docs to new public items.
  • Add //! docs to new public modules.
  • Keep examples current with actual APIs, model constants, module paths, and feature flags.
  • Mark examples no_run when they require external credentials or services.
  • Do not document integrations, features, model constants, or crate paths without checking the code and manifests.
  • Keep root README, crate READMEs, and crate-level Rust docs consistent when changing public-facing behavior.

Provider Changes

Before implementing or modifying a provider, study the closest existing provider implementation. For OpenAI-compatible chat APIs, start with:

crates/rig-core/src/providers/openai/

Provider implementations should include:

  • Provider extension and builder types
  • Provider implementation
  • Capabilities declaration
  • ProviderBuilder implementation
  • client type aliases
  • model constants where useful
  • request conversion from Rig request types
  • response conversion into Rig response types
  • streaming support when the provider supports streaming
  • telemetry spans following existing GenAI conventions
  • tests or examples appropriate to the provider

Do not add request or response fields that do not exist in the provider's real API.

Vector Store Changes

Vector stores should live in companion crates unless there is a strong reason to place them in rig-core.

Implement both:

  • top_n
  • top_n_ids

Use an appropriate backend-specific filter type.

Return VectorStoreError variants instead of ad hoc string errors.

Use WasmCompatSend and WasmCompatSync bounds.

Agent Hook Changes

Agent hooks are per-run lifecycle observers: a single AgentHook<M>::on_event(StepEvent) -> Flow method, composed in registration order via HookStack (the first hook to return a non-Continue Flow short-circuits the rest).

When modifying hook behavior, preserve the intended control flow. Flow is fail-closed — an action an event cannot honor terminates the run rather than silently proceeding:

  • Flow::Continue (observe only)
  • Flow::Terminate
  • Flow::Skip (tool call / invalid tool call only)
  • Flow::Fail / Flow::Retry / Flow::Repair (invalid tool call only)

Check both streaming and non-streaming paths (AgentRunner::stream and AgentRunner::run share one drive loop).

Style

  • Use full where clauses for complex trait bounds.
  • Comments should explain why, not restate what the code does.
  • Follow local naming, module layout, and test patterns.
  • Avoid unrelated refactors.

Verification

Run the smallest useful checks first, then broaden as needed.

Before considering code complete, run when feasible:

cargo fmt
cargo clippy --all-targets --all-features
cargo test

For documentation changes, also consider:

cargo doc --workspace --no-deps

If a command cannot be run, say why and tell the user exactly what remains unverified.