diff --git a/src/deep_research/starter.rs b/src/deep_research/starter.rs index adb4a61..809cf0d 100644 --- a/src/deep_research/starter.rs +++ b/src/deep_research/starter.rs @@ -44,8 +44,20 @@ pub(crate) async fn start() -> anyhow::Result<()> { async fn research(topic: &str) -> anyhow::Result { let client = ollama::Client::new(Nothing)?; + let findings = gather_findings(&client, topic).await?; + let report = write_report(&client, topic, &findings).await?; + + Ok(report) +} + +/// Wraps the tool-calling research loop in its own span so it's visible as a +/// single unit in traces, distinct from the writing phase and nesting rig's +/// own per-turn `chat`/`execute_tool` spans underneath it. +#[tracing::instrument(skip(client), fields(gen_ai.agent.name = "researcher"))] +async fn gather_findings(client: &ollama::Client, topic: &str) -> anyhow::Result { let researcher = client .agent(RESEARCHER_MODEL) + .name("researcher") .preamble( "You are a meticulous research assistant. Use the search_web and fetch_page tools to \ investigate the user's topic: run several searches with varied phrasing, fetch the \ @@ -59,8 +71,6 @@ async fn research(topic: &str) -> anyhow::Result { .tool(FetchPage) .build(); - tracing::info!(topic, "starting research phase"); - let findings = researcher .runner(topic) .max_turns(MAX_RESEARCH_TURNS) @@ -68,10 +78,16 @@ async fn research(topic: &str) -> anyhow::Result { .await? .output; - tracing::info!(findings = %findings, "research phase complete, starting writing phase"); + tracing::info!(findings = %findings, "research phase complete"); + Ok(findings) +} + +#[tracing::instrument(skip(client, findings), fields(gen_ai.agent.name = "writer"))] +async fn write_report(client: &ollama::Client, topic: &str, findings: &str) -> anyhow::Result { let writer = client .agent(WRITER_MODEL) + .name("writer") .preamble( "You turn raw research notes into a clear, well-organized report for the reader. \ Structure the report with headings, cite source URLs inline next to the claims they \