Monitoring
DAIV reports on its agent runs in two places. LangSmith holds the trace of each run: latency, tool calls and intermediate steps. DAIV's own database holds each run's token usage and estimated cost, and a copy of each session's conversation. This page covers both, and the log events DAIV writes when something needs an operator.
Trace runs with LangSmith
DAIV sends a trace of every agent run to LangSmith once you set three variables. You need a LangSmith account.
- In LangSmith, select Settings → API Keys → Create API Key.
- Copy the key.
-
Set
LANGSMITH_TRACINGtotrue,LANGSMITH_PROJECTto the project to write traces to, andLANGSMITH_API_KEYto the key. Monitoring (LangSmith) describes each variable, including the Docker secret form of the key and the EU endpoint.YAML Replace
<langsmith-api-key>with your LangSmith API key. -
Recreate the services so they read the variables. On Docker Compose, run:
Bash On Docker Swarm, run:
Bash -
Start a run, for example a chat in the dashboard. A trace appears in your LangSmith project.
Trace tags and metadata
Every agent run carries tags and metadata that you can filter and group by in LangSmith. The title and commit message generation run has its own, described below.
An agent run has these tags:
| Tag | Description | Example |
|---|---|---|
| Git platform | The platform of the repository | gitlab, github |
| Repository slug | The repository the run targets | group/project |
| Scope | The conversation scope | Issue, Merge Request, Global |
| Agent name | The agent that ran | DAIV Agent |
The scope tag is absent when the run has no scope. A run on a labelled GitLab issue carries gitlab, group/project, Issue and DAIV Agent.
Its metadata holds these fields:
| Field | Type | Description |
|---|---|---|
repository |
string | Repository slug, for example group/project |
git_platform |
string | gitlab or github |
scope |
string | Issue, Merge Request or Global |
trigger |
string | What started the run: label, mention, job, chat or diff_to_metadata |
model |
string | Primary model of the run, as a full model spec such as openrouter:anthropic/claude-sonnet-5.5 |
thinking_level |
string | Thinking level of the run; absent when the run has none |
lc_agent_name |
string | The agent name, DAIV Agent |
author |
string | User who created the issue or merge request (issue and merge request runs) |
triggered_by |
string | User who triggered the run, who differs from the author on a mention (issue and merge request runs) |
issue_id |
int | Issue IID (issue runs) |
labels |
list | The issue's labels, lowercased (issue runs) |
merge_request_id |
int | Merge request ID (merge request runs) |
ref |
string | The branch the run was asked to use (job runs) |
override_source |
string or null | explicit when the request picked the model, otherwise null (job and chat runs) |
A run on a labelled issue has trigger set to label, and a run started by an @daiv mention on an issue, or on a merge request no session owns, has it set to mention. A chat message that starts a run on an idle session has chat and the Global scope. Every run DAIV takes from a session's inbox has job and the Global scope, as do runs from the jobs API, a schedule or the MCP endpoint. The inbox holds pipeline watch fixes, chat messages queued while the session was busy, delegation resumes and leg follow-ups, and @daiv mentions on a merge request the session owns.
The pull request title and commit message generation runs as a separate run named and tagged DiffToMetadata, with trigger set to diff_to_metadata. It carries the git platform, repository and scope tags and no agent name tag. It nests under the agent trace when DAIV publishes at the end of a run, and stands alone when DAIV recovers a draft.
Create the LangSmith dashboard
DAIV creates a LangSmith dashboard named DAIV Monitoring with 27 charts in 8 groups, built on the tags and metadata above. You need the LangSmith variables from Trace runs with LangSmith set in the container.
Warning
Recreating the dashboard with --recreate deletes the existing DAIV Monitoring dashboard, including any chart you added by hand. setup_langsmith_dashboard describes it.
-
Run the command, with your project name:
Bash Replace
<project-name>with your LangSmith project. -
In LangSmith, open the DAIV Monitoring dashboard of your project.
After you upgrade DAIV, run the command with --recreate to add the charts the upgrade brings.
| Group | Charts | What it tracks |
|---|---|---|
| Overview | Trace volume and error rate by scope, trigger breakdown | Activity and reliability |
| Latency | Median and P99 latency by scope, latency by repository | Response times |
| Cost | Total cost by scope, prompt against completion cost, token usage by repository, P99 cost per run by trigger | Spend |
| Platform | Volume and error rate by git platform, top repositories by volume | Platform and repository breakdown |
| Tools | Subagent usage, tool call volume, tool error rate, MCP server tool usage | What the agent calls |
| LLM | Call count, latency, prompt against completion tokens | Model calls |
| Model | Trace volume, latency, cost and error rate by model | Per-model comparison |
| DiffToMetadata | Volume, latency, error rate | Title and commit message generation |
To compare models, group a chart by the model metadata field. To see who starts the runs, group by author or triggered_by.
Usage and cost
DAIV records the token usage and an estimated cost for every agent run in its own database, without a LangSmith account.
DAIV counts the tokens of every model call in the run, including fallback models, models that tools call, and subagents, and prices each call on its own. For a call through OpenRouter, the cost is the charge OpenRouter reports, which depends on the provider it routed the call to. For any other call, DAIV estimates it from the model's list price in genai-prices. DAIV then totals the tokens and cost per model, and stores the totals on the run.
A run records:
| Field | Description |
|---|---|
input_tokens |
Input tokens across all model calls |
output_tokens |
Output tokens across all model calls |
total_tokens |
Input plus output tokens |
cost_usd |
The run's cost in US dollars |
usage_by_model |
The same figures per model, with the cache and reasoning token counts the provider reports |
Two limits apply:
- For a call DAIV prices from list prices, the cost is empty when genai-prices does not list the model, and a run's cost is empty when any of its calls has no price. The tokens are still recorded, and DAIV logs a warning naming the model.
- A cost priced from list prices is an estimate. Your provider's bill can differ.
You see the figures in three places. A row in the sessions list shows the session's cost, the Spend section of a session's Overview shows what the session cost, and a run's downloaded Markdown result holds total_tokens and cost_usd in its front matter. Sessions describes the pages.
Export session archives
DAIV writes a copy of each session's conversation to its database when each run ends. This session archive is the saved copy, not a session's Archived state. The copy outlives the checkpointer's time to live and LangSmith's retention, and you can export it for offline analysis.
Warning
An export holds full conversations and run prompts. Store the output directory as you would the repositories' contents, and delete it when you finish.
- Run
export_session_archiveswith an output directory, and with--sinceand--repoto narrow the sessions. The command's page holds the commands that write the files inside the container, copy them to the host and remove them. - Open
<thread_id>.jsonfor each session.
Each file holds the session's repository, origin and title, and its contexts in order, where a /clear closes one context and starts the next and closed_at says when. Each context holds its messages in LangChain's messages_to_dict format. The file also holds each run's status, model, tokens and cost. The archive holds the session's messages, not each model request: system prompts, tool schemas, summaries and subagent internals stay in LangSmith. When a session fails to export, the command logs and names it, writes the rest, then exits with an error.
Log events
DAIV writes these events to its logs. Alert on them or search for them to find a problem early.
Archive events
The daiv.sessions logger reports archive trouble. Errors reach Sentry.
| Level | Message | Meaning |
|---|---|---|
| ERROR | executor: failed to archive thread_id=… |
A run's end was not archived, and the traceback says why, a timeout included. The next run's archive catches up. |
| ERROR | Thread … holds N messages, fewer than its archived M; keeping the archive |
The live thread lost messages the archive holds. DAIV leaves the archive as it was. |
| ERROR | Failed to load archived context N of thread …; leaving it out |
An archive row no longer decodes, and the transcript shows without it. |
| WARNING | No session … to archive its thread under |
A thread has no session, so DAIV archives nothing. |
| INFO | Restored thread … from archived context N |
An expired thread was seeded from its archive before a run. |
A context that exists but fails to restore fails the run with ArchiveRestoreError and is not logged as one of these events.
Bash policy events
The daiv.tools logger writes a warning when the sandbox bash tool blocks a command, or cannot parse one and so blocks it.
| Text Only | |
|---|---|
| Text Only | |
|---|---|
Each record carries these fields:
| Field | Description |
|---|---|
event |
bash_policy_denied or bash_policy_parse_failed |
reason_category |
default_disallow, global_disallow or parse_failure |
matched_rule |
The rule that blocked the command, for example git push; on bash_policy_denied only |
denied_segment |
The part of the command that was blocked; on bash_policy_denied only |
tool_call_id |
The agent's tool call ID, which matches the tool call in the LangSmith trace |
default_disallow is a built-in rule, and global_disallow is a rule you set in DAIV_SANDBOX_COMMAND_POLICY_DISALLOW. A spike in bash_policy_denied means the agent keeps attempting a blocked command.
Troubleshooting
No traces appear in LangSmith
Check that LANGSMITH_TRACING is true and that the API key is correct. Check that the containers can reach the LangSmith endpoint, and read the application logs for authentication errors.
A trace is incomplete
Check that the project name is the same in every service. On Docker Swarm, check that the secret holding the API key is mounted.