use std::sync::Arc;
use agent_kernel::{Agent, AgentEvent, AgentRuntime, BoxFuture, Message, Role, discuss};
use tokio::sync::mpsc;
use tokio_util::sync::CancellationToken;
#[derive(Clone)]
struct HttpRuntime {
_client: Arc<()>,
base_url: String,
api_key: String,
}
impl HttpRuntime {
fn new(base_url: impl Into<String>, api_key: impl Into<String>) -> Self {
Self {
_client: Arc::new(()),
base_url: base_url.into(),
api_key: api_key.into(),
}
}
}
impl AgentRuntime for HttpRuntime {
fn respond<'a>(
&'a self,
agent: &'a Agent,
history: &'a [Message],
) -> BoxFuture<'a, anyhow::Result<String>> {
Box::pin(async move {
let _ = (&self.base_url, &self.api_key); let _ = history.iter().filter(|m| m.role != Role::System).count();
Ok(format!(
"[{}] (stub) I would call {} here.",
agent.name, self.base_url
))
})
}
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let api_key = std::env::var("ANTHROPIC_API_KEY").unwrap_or_else(|_| "stub-key".to_string());
let runtime = HttpRuntime::new("https://api.anthropic.com", api_key);
let agents = vec![
Agent {
name: "analyst".to_string(),
soul_md: "You are a senior software architect. Be precise and concise.".to_string(),
model: "claude-sonnet-4-6-20250514".to_string(),
},
Agent {
name: "critic".to_string(),
soul_md: "You are a critical reviewer. Identify risks and edge cases.".to_string(),
model: "claude-sonnet-4-6-20250514".to_string(),
},
];
let (tx, mut rx) = mpsc::channel::<AgentEvent>(64);
let cancel = CancellationToken::new();
let collector = tokio::spawn(async move {
let mut events = Vec::new();
while let Some(event) = rx.recv().await {
println!("{event:?}");
events.push(event);
}
events
});
let summary = discuss(
&runtime,
&agents,
"Should we migrate our REST API to GraphQL?",
2,
cancel,
tx,
)
.await?;
let events = collector.await?;
println!("\nTotal events: {}", events.len());
println!("Summary: {summary}");
Ok(())
}