Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion weave.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ W&B Weave provides Python and TypeScript libraries. To install the Weave library
</Tab>
<Tab title="TypeScript">
```bash
pnpm install weave
npm install weave
```
</Tab>
</Tabs>
Expand Down
83 changes: 68 additions & 15 deletions weave/cookbooks/source/agents-quickstart.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
"source": [
"# Quickstart: Trace an agent\n",
"\n",
"Trace a multi-turn agent with the Weave SDK. Sessions, turns, LLM calls, and tool calls render in the Agents view of your project.\n",
"Trace a multi-turn agent with the Weave SDK. Conversations, turns, LLM calls, and tool calls render in the Agents view of your project.\n",
"\n",
"The Weave SDK allows you to trace custom agents or agents created using popular SDKs. This quickstart guides you through how to manually integrate Weave into a custom-built multi-turn agent to emit and capture OpenTelemetry spans and render them in Weave's Agents view.\n",
"\n",
"If you are looking to integrate Weave with popular SDKs or harnesses, such as the Claude Agents SDK or Codex, see the [Weave integration section](https://docs.wandb.ai/weave/guides/integrations). Weave autopatches into several popular agent-building SDKs and agent harnesses for quick integration.\n",
"If you are looking to integrate Weave with popular SDKs or harnesses, such as the Claude Agents SDK or Codex, see [Choose an agent integration](https://docs.wandb.ai/weave/agent-integration-quickstart). Weave autopatches into several popular agent-building SDKs and agent harnesses for quick integration.\n",
"\n",
"## What you'll learn\n",
"\n",
Expand All @@ -19,18 +19,19 @@
"This guide shows you how to:\n",
"\n",
"- Initialize Weave for agent tracing with `weave.init()`\n",
"- Open a session and a turn with `weave.start_session()` and `weave.start_turn()`\n",
"- Open a conversation and a turn with `weave.start_conversation()` and `weave.start_turn()`\n",
"- Wrap LLM calls with `weave.start_llm()` and record usage\n",
"- Wrap tool executions with `weave.start_tool()` and record results\n",
"- View the resulting session, turns, and tool calls in the Agents view\n",
"- Record complete token usage and a priceable model so token counts and cost render\n",
"- View the resulting conversation, turns, and tool calls in the Agents view\n",
"\n",
"## How the Weave SDK works with agents\n",
"\n",
"The Weave SDK includes a generic OTel ingest system for agents, meaning that Weave can capture information from any OTel span in your agent's code. However, Weave requires special handling of the following spans to render your agent's traces in the Agents view of the Weave UI.\n",
"\n",
"| Function | Maps to | OTel span |\n",
"| --- | --- | --- |\n",
"| `weave.start_session(...)` | A conversation | (no span — groups turns) |\n",
"| `weave.start_conversation(...)` | A conversation | (no span — groups turns) |\n",
"| `weave.start_turn(...)` | One user / agent exchange | `invoke_agent` |\n",
"| `weave.start_llm(...)` | One LLM API call | `chat` |\n",
"| `weave.start_tool(...)` | One tool execution | `execute_tool` |\n",
Expand Down Expand Up @@ -141,7 +142,7 @@
"source": [
"## Run a traced multi-turn agent\n",
"\n",
"The example below runs three turns in a single session. Each turn:\n",
"The example below runs three turns in a single conversation. Each turn:\n",
"\n",
"1. Opens a `chat` span and lets the LLM decide whether to call the tool\n",
"2. If the LLM requested a tool, opens an `execute_tool` span around the call and feeds the result back to the LLM\n",
Expand Down Expand Up @@ -170,9 +171,17 @@
" )\n",
" msg = resp.choices[0].message\n",
" llm.output(msg.content or \"\")\n",
" llm.usage = weave.Usage(\n",
" input_tokens=resp.usage.prompt_tokens,\n",
" output_tokens=resp.usage.completion_tokens,\n",
" # record() sets usage, the priced model, and response id in one call.\n",
" llm.record(\n",
" usage=weave.Usage(\n",
" input_tokens=resp.usage.prompt_tokens,\n",
" output_tokens=resp.usage.completion_tokens,\n",
" cache_read_input_tokens=getattr(\n",
" resp.usage.prompt_tokens_details, \"cached_tokens\", 0\n",
" ),\n",
" ),\n",
" response_id=resp.id,\n",
" response_model=resp.model,\n",
" )\n",
" history.append(msg.model_dump(exclude_none=True))\n",
"\n",
Expand All @@ -199,14 +208,21 @@
" resp = openai_client.chat.completions.create(model=MODEL, messages=history)\n",
" msg = resp.choices[0].message\n",
" llm.output(msg.content)\n",
" llm.usage = weave.Usage(\n",
" input_tokens=resp.usage.prompt_tokens,\n",
" output_tokens=resp.usage.completion_tokens,\n",
" llm.record(\n",
" usage=weave.Usage(\n",
" input_tokens=resp.usage.prompt_tokens,\n",
" output_tokens=resp.usage.completion_tokens,\n",
" cache_read_input_tokens=getattr(\n",
" resp.usage.prompt_tokens_details, \"cached_tokens\", 0\n",
" ),\n",
" ),\n",
" response_id=resp.id,\n",
" response_model=resp.model,\n",
" )\n",
" history.append({\"role\": \"assistant\", \"content\": msg.content})\n",
" return msg.content\n",
"\n",
"with weave.start_session(agent_name=\"research-bot\") as session:\n",
"with weave.start_conversation(agent_name=\"research-bot\") as conversation:\n",
" history = []\n",
" for question in [\n",
" \"Who founded Anthropic?\",\n",
Expand All @@ -217,6 +233,43 @@
" print(f\"AGENT: {run_turn(history, question)}\\n\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Record token usage and cost\n",
"\n",
"Each `chat` span carries token usage and a model id. Weave renders token counts from usage and derives cost from usage plus the model id, so an incomplete or unpriceable value shows `0 in / 0 out` tokens or `Cost -` even when the rest of the trace looks correct. `record(...)` sets these fields (along with `output_messages`, `response_id`, `reasoning`, and more) in one call. Only the fields you pass are applied.\n",
"\n",
"Two things must be right for cost to appear:\n",
"\n",
"- **Complete usage.** `input_tokens` is the *total* input, including any cached tokens. Weave prices cache reads and cache writes at their own rates and subtracts them from the input total, so `cache_read_input_tokens` and `cache_creation_input_tokens` must be reported *in addition to* a total `input_tokens` that includes them. For providers with prompt caching (for example, Anthropic), cached tokens routinely dominate the input, so omitting them makes usage and cost render as roughly zero.\n",
"- **A priceable model id.** Cost is a lookup on the model. Weave prefers `response_model` (the exact model the provider served) and falls back to the `model` you passed to `start_llm`. An alias such as `opus` or `sonnet` is not priceable and renders `Cost -`, so pass the concrete id the response returns (`resp.model`) as `response_model`.\n",
"\n",
"OpenAI counts cached tokens inside `prompt_tokens`, so the agent above maps directly. Anthropic reports cached tokens *separately* from `input_tokens`, so add them back into the total Weave prices against. The following snippet is illustrative — this notebook uses OpenAI, so there's no `anthropic_client` to run it against:\n",
"\n",
"```python\n",
"with weave.start_llm(model=MODEL, provider_name=\"anthropic\") as llm:\n",
" resp = anthropic_client.messages.create(\n",
" model=MODEL, max_tokens=1024, messages=history,\n",
" )\n",
" u = resp.usage\n",
" llm.output(resp.content[0].text)\n",
" llm.record(\n",
" usage=weave.Usage(\n",
" input_tokens=u.input_tokens\n",
" + u.cache_read_input_tokens\n",
" + u.cache_creation_input_tokens,\n",
" output_tokens=u.output_tokens,\n",
" cache_read_input_tokens=u.cache_read_input_tokens,\n",
" cache_creation_input_tokens=u.cache_creation_input_tokens,\n",
" ),\n",
" response_id=resp.id,\n",
" response_model=resp.model,\n",
" )\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
Expand All @@ -226,7 +279,7 @@
"When `weave.init()` runs, it prints a link to your project where you can see:\n",
"\n",
"- A row in the **Agents** tab for `research-bot`\n",
"- One session containing three turns\n",
"- One conversation containing three turns\n",
"- Each turn (`invoke_agent`) with two `chat` spans and an `execute_tool` span nested inside\n",
"- Token counts, latency, model, and the full message exchange on each `chat`\n",
"\n",
Expand All @@ -235,7 +288,7 @@
"## Next steps\n",
"\n",
"- Get a better understanding of how to [trace agents with Weave](https://docs.wandb.ai/weave/guides/tracking/trace-agents) and what features and options are available in the Weave SDK.\n",
"- See the [integration section](https://docs.wandb.ai/weave/guides/integrations) for more options on how to integrate Weave with your agents."
"- See [Choose an agent integration](https://docs.wandb.ai/weave/agent-integration-quickstart) for more options on how to integrate Weave with your agents."
]
}
],
Expand Down
Loading
Loading