Skip to main content

Crate agent_abstraction

Crate agent_abstraction 

Source
Expand description

Drive Claude Code, Codex and GitHub Copilot headlessly from Rust.

One request type, one event vocabulary and one session model across three agent CLIs that agree on none of those things. This is a library: your program links it and spawns the agent itself, with no intermediate CLI marshalling a request through stdout and back.

§Running a prompt

use agent_abstraction::{Agent, Permission, Request, run};

let outcome = run(
    &Request::new(Agent::Claude, "Reply with the single word: pong")
        .model("haiku")
        .permission(Permission::ReadOnly),
)
.await?;

println!("{}", outcome.text);

§Watching one as it works

use agent_abstraction::{Agent, Event, Request, stream};

let mut running = stream(&Request::new(Agent::Claude, "audit this repo"))?;
while let Some(event) = running.recv().await {
    match event {
        Event::Text(text) => print!("{text}"),
        Event::ToolCall { name, .. } => println!("[{name}]"),
        _ => {}
    }
}
let outcome = running.finish().await?;

§Multi-turn conversations

Thread one stable name across turns and let SessionStore map it to whatever handle the agent understands:

use agent_abstraction::{Agent, Request, SessionStore, run};

let store = SessionStore::open("/var/lib/myapp/sessions");

// First turn creates the session; later turns continue it.
let first = Request::new(Agent::Claude, "remember the number 7")
    .session(&store, ".", "thread-42", false)?;
run(&first).await?;

let second = Request::new(Agent::Claude, "what number did I say?")
    .session(&store, ".", "thread-42", false)?;
println!("{}", run(&second).await?.text);

§What each agent can do

session idforkeventssystem prompt
Claude Codecaller-minted (--session-id)yesyesnative flag
Codexagent-printed (thread_id)noyesprepended
Copilotcaller-minted (--session-id)noyesprepended

Asking for something an agent cannot do is always an Error::Unsupported, never a silent downgrade. A caller that asked to fork and got a linear resume would corrupt the conversation it meant to branch.

§Operating within the agents’ terms

This crate drives each vendor’s own supported headless interface with the credentials that CLI already uses. It does not reimplement a provider API, multiplex accounts, or retry around a quota: a refusal surfaces as Error::RateLimited, carrying the provider’s own wording, and backing off is the caller’s decision. See docs/operating-limits.md.

Structs§

Caps
What an agent supports. Used to reject an impossible request before spawning rather than silently doing something weaker than asked.
Outcome
The result of one completed run.
RateLimit
A quota signal the agent emitted mid-run.
Request
A run, described but not yet started.
Run
A run in progress.
SessionRecord
One named conversation.
SessionStore
The store of named sessions.
Usage
Token and cost accounting for a run.

Enums§

Agent
A coding agent this crate can drive headlessly.
EnvPolicy
Which of the host’s environment variables reach the agent.
Error
Everything that can go wrong driving an agent CLI.
Event
One normalized thing an agent did, agent-agnostic so a single renderer works across all three.
Format
Output shape requested from the agent.
Permission
Permission posture for a run, mapped onto each agent’s own vocabulary.
Phase
Whether the next turn starts a conversation or continues one.
SessionSupport
How an agent’s native session id is obtained. This is the axis deciding whether a caller-owned session name can be bound to it at all.
Stop
Why the agent stopped.

Constants§

MAX_CAPTURE
The ceiling on any single captured buffer.
NETWORK_ENV
Environment variables that route an agent’s traffic through a corporate proxy or a custom certificate authority.

Functions§

run
Run request to completion, discarding the intermediate events.
stream
Start request, returning a handle that streams its events.

Type Aliases§

Result
Result alias for this crate.