Skip to main content

recursive/llm/
mod.rs

1//! LLM provider abstraction.
2//!
3//! A provider takes a transcript plus tool specs and returns either
4//! free-form content, structured tool calls, or both. The trait is the
5//! only thing the agent depends on; everything beyond it (HTTP, retries,
6//! mocking) lives in adapters.
7
8use async_trait::async_trait;
9use serde::{Deserialize, Serialize};
10use serde_json::Value;
11
12use crate::error::Result;
13use crate::message::Message;
14
15pub mod mock;
16pub mod openai;
17
18pub use mock::MockProvider;
19pub use openai::OpenAiProvider;
20
21/// JSON-schema description of a tool, sent verbatim to the model.
22#[derive(Debug, Clone, Serialize, Deserialize)]
23pub struct ToolSpec {
24    pub name: String,
25    pub description: String,
26    /// JSON Schema object describing the tool's input.
27    pub parameters: Value,
28}
29
30/// A structured request to invoke one of the registered tools.
31#[derive(Debug, Clone, Serialize, Deserialize)]
32pub struct ToolCall {
33    pub id: String,
34    pub name: String,
35    /// Raw JSON arguments as produced by the model.
36    pub arguments: Value,
37}
38
39/// One step of model output.
40#[derive(Debug, Clone)]
41pub struct Completion {
42    pub content: String,
43    pub tool_calls: Vec<ToolCall>,
44    pub finish_reason: Option<String>,
45}
46
47#[async_trait]
48pub trait LlmProvider: Send + Sync {
49    async fn complete(&self, messages: &[Message], tools: &[ToolSpec]) -> Result<Completion>;
50}