Skip to content

feat: trace cron-fired agent runs alongside chat - #19

Merged
nshi merged 1 commit into
masterfrom
feat/cron-trace-logging
May 9, 2026
Merged

feat: trace cron-fired agent runs alongside chat#19
nshi merged 1 commit into
masterfrom
feat/cron-trace-logging

Conversation

@nshi

@nshi nshi commented May 9, 2026

Copy link
Copy Markdown
Owner

Summary

Cron-triggered agent jobs were silently invoking record_event without a scoped trace context, so events landed in runtime-trace.jsonl with session_id=None and were orphaned in the viewer (`dev/trace-viewer.py`). This change makes cron runs first-class in the trace pipeline — same detail and granularity as chat — and clearly distinguishes them in the viewer.

  • Unified trace context: replaced `RUNTIME_TRACE_SESSION_ID: Option` task-local with a typed `Option<Arc>` carrying `kind` (Chat | Cron), `session_id`, and cron job id/name. Both the channels boundary and the cron scheduler now wrap the agent loop in the same scope; the agent loop itself is unchanged. `Arc` keeps `record_event` cheap at the ~26 call sites in the agent loop (pointer clone, not 4× String clone).
  • Cron lifecycle bookends: `cron_job_started` (with job_id/name/schedule/prompt/model_override/run_id) and `cron_job_finished` (with success/duration_ms/output_preview) frame each firing — analogue of `channel_message_inbound/outbound` for chat. Heavy payload construction is gated behind `runtime_trace::is_enabled()` so it's skipped when `runtime_trace_mode = "none"`.
  • Viewer support: `Turn` and `ConversationSession` track `kind` / `cron_job_id` / `cron_job_name`. Cron sessions render with a yellow `[CRON]` tag and `job=` instead of channel. New `--kind {chat,cron,all}` filter. `search_sessions` now matches cron metadata as well as inbound chat content.
  • Backwards compatible: legacy JSONL events without `kind` parse via serde defaults (default = Chat).

Test plan

  • `cargo fmt --check` — clean
  • `cargo clippy --all-targets -- -D warnings` — clean
  • `cargo test --lib` — 4281 tests pass; new tests cover (a) legacy events without `kind` deserialize as Chat, (b) `record_event` under `TraceContext::cron` populates kind/job_id/job_name and `session_id == run_id`
  • Viewer smoke test on a synthesized JSONL: `--kind cron`, `--kind chat`, and `search ` all render correctly with the `[CRON]` tag
  • Manual end-to-end (after merge): schedule a one-shot agent cron `mentat cron add agent --at "+30s" --prompt "..."`, wait for it to fire, then `tail ~/.mentat/workspace/state/runtime-trace.jsonl | jq 'select(.kind=="cron")'` and confirm `cron_job_started` → `provider_api_request` → `cron_job_finished` all share the same `session_id`. Then `uv run dev/trace-viewer.py recent --count 5` should show the run with the `[CRON]` tag.

Cron-triggered agent jobs were silently invoking record_event without a
scoped trace context, so events landed in runtime-trace.jsonl with
session_id=None and were orphaned in the viewer. Widen the trace context
from a bare session id to a typed TraceContext (kind=Chat|Cron, plus
cron job id/name) propagated via the same task-local; both the channels
boundary and the cron scheduler now scope it the same way. The viewer
gains a [CRON]-tagged session group, --kind filter, and search-by-job-name.

- runtime_trace: replace RUNTIME_TRACE_SESSION_ID with RUNTIME_TRACE_CONTEXT
  carrying TraceKind + cron metadata; wrap in Arc so record_event clones a
  pointer instead of 4 Strings per agent-loop call. Add is_enabled() so
  callers can skip heavy payload construction when tracing is off. Legacy
  JSONL parses via serde defaults (kind→Chat).
- cron::scheduler::run_agent_job: scope agent::run in TraceContext::cron
  with a per-firing run_id; emit cron_job_started / cron_job_finished
  bookends so the viewer has session anchors analogous to chat's
  channel_message_inbound/outbound.
- trace-viewer.py: add kind/cron_job_id/cron_job_name to Turn and
  ConversationSession; render cron sessions with a yellow [CRON] tag;
  add --kind {chat,cron,all}; search matches cron_job_id/_name and the
  cron_job_started prompt.
@nshi
nshi merged commit a8aa094 into master May 9, 2026
14 of 17 checks passed
@nshi
nshi deleted the feat/cron-trace-logging branch May 9, 2026 21:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant