Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Serving an agent

Implement Agent and hand it to one of the serve_* functions. Only initialize, new_session and prompt are required — advertise whatever else you implement in InitializeResponse::agent_capabilities.

use cacp::{Agent, Result, schema};
use std::sync::Arc;

struct Echo;

impl Agent for Echo {
    async fn initialize(&self, _: schema::InitializeRequest) -> Result<schema::InitializeResponse> {
        Ok(schema::InitializeResponse {
            protocol_version: schema::ProtocolVersion::LATEST,
            agent_capabilities: Default::default(),
            auth_methods: Vec::new(),
            agent_info: None,
            meta: None,
        })
    }

    async fn new_session(
        &self,
        _: schema::NewSessionRequest,
    ) -> Result<schema::NewSessionResponse> {
        Ok(schema::NewSessionResponse {
            session_id: "session-1".into(),
            modes: None,
            config_options: None,
            meta: None,
        })
    }

    async fn prompt(&self, _: schema::PromptRequest) -> Result<schema::PromptResponse> {
        Ok(schema::PromptResponse::new(schema::StopReason::EndTurn))
    }
}

#[tokio::main]
async fn main() {
    let _client = cacp::serve_on_stdio(Arc::new(Echo));
    // The read and write loops run on the runtime; keep the process alive.
    std::future::pending::<()>().await
}

That is crates/cacp/examples/agent.rs, included verbatim — cargo test compiles it, so this page cannot drift from working code.

serve_on_stdio hands back a ClientConn for calling the editor — reporting progress with session_update, asking permission, reading files through it.

Three ways in, depending on what you already hold:

functiontakes
serve_on_stdiothis process’s own stdin and stdout
serveone duplex stream — a socket, an in-memory pipe
serve_ona reader and a writer owned separately