Skip to main content

Documentation Index

Fetch the complete documentation index at: https://cognis.vasanth.xyz/llms.txt

Use this file to discover all available pages before exploring further.

An agent is a model that can call tools and decide when to stop. Behind the scenes, every Cognis agent is a compiled Graph<AgentState> with a small set of nodes — a model node that asks the LLM what to do, a tool-dispatch node that runs the calls, and edges that loop until the model has nothing left to do. You can build that graph by hand, but you usually don’t need to. AgentBuilder carries the opinion that most agents look the same, and gives you a builder for the parts that change.

What an agent is, exactly

       ┌──────┐
 ──→   │ model │  ──→  emits tool calls?
       └──────┘             │
            ▲      yes ─────┴───── no ──→ done

       ┌────────┐                        
       │  tools  │  ←── dispatch each call
       └────────┘
That’s the whole loop. Everything Cognis adds — memory, middleware, multi-agent, human-in-the-loop — sits around this loop without changing its shape.

When to use an agent

  • The model needs to make multiple decisions before answering.
  • You want it to reach for tools (search, calculator, API lookups, your domain functions).
  • You want a transcript the user can replay.
If you just need a one-shot answer, call Client::invoke(messages) directly. If you need branching that doesn’t fit the loop shape, drop down to a Graph<S>.

Quick example

use std::sync::Arc;
use cognis::prelude::*;
use cognis::{AgentBuilder, Calculator};
use cognis_llm::Client;

let mut agent = AgentBuilder::new()
    .with_llm(Client::from_env()?)
    .with_tool(Arc::new(Calculator::new()))
    .with_system_prompt("You are a math assistant.")
    .with_max_iterations(4)
    .build()?;

let resp = agent.run(Message::human("What is 23 * 17 + 4?")).await?;
println!("{}", resp.content);
agent.run(impl Into<Message>) returns an AgentResponse carrying:
  • content: String — the final assistant reply.
  • messages: Vec<Message> — the full transcript, including tool calls and tool results.

How it works

When you call agent.run:
  • Memory seeds the conversation. If you set one (with_memory), the agent prepends those messages.
  • The model is invoked with current messages and tool definitions. with_max_iterations caps how many times the loop can ask.
  • If the reply has tool calls, the tool dispatcher runs them, threads the results back as Message::tool entries, and loops.
  • If it doesn’t, the loop exits and the model’s last reply becomes resp.content.
  • Middleware wraps each model call. Retry, fallback, rate limits, redaction, prompt caching, planning — all hook into this loop without rewriting it.

Customization knobs

AgentBuilder exposes everything you’d want to change about that loop:
MethodWhat changes
.with_llm(Client)The model. Required.
.with_tool(Arc<dyn Tool>) / .with_tools(...)What the agent can call.
.with_system_prompt(...)Role / persona / rules.
.with_memory(impl Memory)What context survives between run calls.
.with_max_iterations(n)Hard cap on loop iterations.
.with_max_tool_calls(n)Hard cap on total tool invocations.
.with_filesystem(Arc<dyn Backend>)Mounts a virtual filesystem the model can read/write.
.with_approver(Arc<dyn Approver>)Human-in-the-loop tool gating.
.stateful() / .stateless()Persist or reset state across run.
.with_graph(graph)Replace the default ReAct graph entirely.
Pages that go deep on each of these:

When the loop isn’t enough

Sometimes you want behavior the loop can’t express — fan-out across heterogeneous workers, persistence-aware time travel, structured handoffs between agents with different state shapes. Then you have two paths:
  • Multi-agent orchestration. MultiAgentOrchestrator::new(strategy).add(...).run(...) runs several agents under a strategy.
  • Hand-built graph. Graph<MyState>::new()....compile()? then either drive it directly, or Agent::wrap(graph) to slot it into the agent surface.
Both keep AgentResponse as the output type, so callers don’t change.

See also

Quickstart

The fastest path to a working agent.

Tools

Define what the agent can do.

Multi-agent

When one agent isn’t enough.

Graphs

The substrate behind the loop.