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

API Integration

Provider code formats requests and parses responses in core. The host carries them out asynchronously: the Zellij adapter uses its web-request API, while Montana implements the component’s HTTP import with a native client and sends the completion back as a host event. Provider logic does not depend on a terminal or Zellij panes. Proxy routing, credentials and network policy still depend on the deployment.

Source: crates/core/src/provider/.

Providers

Six providers implement the LlmProvider trait, selected by ProviderType:

  • ClaudeProvider (Anthropic Messages API)
  • OpenAIProvider (Chat Completions / Responses API)
  • CodexProvider (ChatGPT subscription Responses API with SSE)
  • OpenRouterProvider
  • VercelProvider (Vercel AI Gateway, Chat Completions)
  • OllamaProvider (local, keyless)

The LlmProvider trait

The trait does not perform transport I/O. It only serializes requests and deserializes responses:

#![allow(unused)]
fn main() {
pub trait LlmProvider {
    fn name(&self) -> &str;

    fn format_request(
        &self,
        messages: &[Message],
        tools: &[Tool],
        system: &str,
    ) -> (String, BTreeMap<String, String>, Vec<u8>);

    fn parse_response(&self, body: &[u8]) -> Result<LlmResponse, ProviderError>;
    fn parse_error(&self, status: u16, body: &[u8]) -> ProviderError;

    fn set_model(&mut self, model: &str);
    fn api_key(&self) -> &str;
}
}

The request flow is:

  1. format_request() produces (url, headers, body).
  2. Core requests HTTP through its host interface.
  3. The host delivers the correlated HTTP result: a Zellij event or, through Montana, a WIT host event mapped back into core.
  4. parse_response() (on HTTP 200) or parse_error() (otherwise) interprets it.

set_model() supports switching the model at runtime (the /model command).

Credentials

In the managed credential-proxy deployment (services.cowboy.secretsProxy.enable), the agent sends placeholder keys and the proxy injects the real credentials on the wire based on per-domain mappings. Codex is the same pattern: its rotating ChatGPT subscription token is injected outside the agent. Local and ordinary Docker launches hold credentials. See Security Model. For keyless providers (Ollama) api_key() is empty.

Provider defaults

ClaudeProvider targets /v1/messages. Its defaults: model claude-sonnet-4-20250514, max_tokens 8192, extended thinking enabled with a token budget. OpenAIProvider defaults to gpt-4o and auto-selects the Responses API for reasoning models (o-series, gpt-5, codex) to capture reasoning summaries, which are mapped onto thinking content blocks.

Message model

Messages carry a string role and a vector of ContentBlocks, matching the Claude API’s native content-block model. A block’s block_type is one of text, tool_use, tool_result, or thinking.

Errors and retries

ProviderError includes ParseError, ApiError, NetworkError, RateLimited, Timeout, InvalidRequest, AuthenticationError, and Overloaded. is_retryable() marks rate limits (429), network errors, server errors (5xx), and timeouts as retryable; auth and other 4xx errors are not. Automatic retry is wired in: a RetryState with exponential backoff drives a bounded retry of failed LLM calls from the ranch handlers (crates/core/src/handlers.rs, schedule_llm_retry) — a retryable error schedules a backed-off retry until max_attempts is exhausted, after which the failure surfaces as an error message.

Bridges

Bridge services (Discord, email) do not use the provider layer. They reach the agent through the pub/sub message system: inbound messages are polled and processed as user input, and replies flow back out the same way. See Approvals & Outbox.