Turn-level observability — correlation_id binds a question's agent refinements - #54
Merged
Merged
Conversation
…tions)
Migration 009 adds tool_calls.correlation_id; ToolCallRecord + the DB sink +
_TOOL_CALL_COLS carry it; record_tool_call captures args.get('correlation_id').
execute_sql's inputSchema gains a correlation_id param, and SERVER_INSTRUCTIONS
now tells Claude to keep user_question VERBATIM across a turn (refinement only in
raw_query) and mint one correlation_id per user question. Slice A of ACE-015.
model_store._group_turns folds a session's calls into turns (one user question -> N agent queries) keyed on correlation_id; a call with no correlation_id is its own singleton turn (degrades to the old flat list). The turn's question is the EARLIEST call's user_question (drift-proof). _session_drawer renders one 'User asked X · N queries' block per turn with each refinement's agent_query + SQL. Slice B of ACE-015.
render_previews seeds one turn (correlation c1) with two agent queries so the Sessions preview shows the 'User asked X · 2 queries' grouping; README documents the turn level. Slice C of ACE-015.
There was a problem hiding this comment.
Pull request overview
Adds “turn-level” observability to the admin activity log by introducing a correlation_id that groups multiple agent sub-queries spawned from a single user question within a conversation/thread.
Changes:
- Add nullable
correlation_idtotool_calls(migration 009) and plumb it through contracts, sinks, and the tool-call recorder. - Extend
execute_sqltool schema + server instructions so the model self-reports onecorrelation_idper user question/turn and keepsuser_questionverbatim across refinements. - Group session queries into turns in
model_store, and render the Sessions drawer as “User asked … · N queries” blocks; add preview seeds and tests/docs for grouping + drift/degradation behavior.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_admin_activity.py | Adds coverage for correlation_id round-trip, schema/instruction presence, turn grouping (incl. drift + degradation), and Sessions drawer rendering. |
| render_previews.py | Updates preview seed data to include multi-query turns via correlation_id. |
| packages/agami-core/src/tools.py | Records correlation_id from tool args; updates execute_sql input schema + SERVER_INSTRUCTIONS guidance. |
| packages/agami-core/src/model_store.py | Adds correlation_id to tool-call read/write paths and groups session queries into turns (_group_turns). |
| packages/agami-core/src/contracts.py | Extends ToolCallRecord with correlation_id. |
| packages/agami-core/src/admin.py | Renders Sessions drawer grouped by turns instead of a flat per-call list. |
| packages/agami-core/README.md | Documents turn-level grouping semantics and drift behavior in the Sessions tab. |
| migrations/core/009_tool_calls_correlation.sql | Adds correlation_id column to tool_calls. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+318
to
+322
| '<div style="border-top:2px solid var(--line);padding:14px 0 2px;margin-top:8px">' | ||
| f'<div style="margin-bottom:4px"><span class="muted">User asked</span> ' | ||
| f'<strong>{ui.esc(question)}</strong> ' | ||
| f'<span class="muted" style="font-size:13px">· {n} {"query" if n == 1 else "queries"}</span>' | ||
| f"</div>{qrows}</div>" |
Comment on lines
365
to
375
| @@ -373,6 +375,31 @@ def list_tool_calls(store: Store, *, limit: int = 200) -> list[dict[str, Any]]: | |||
| ) | |||
Contributor
Author
|
Thanks @copilot:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Spec: ACE-015
Summary
Adds the turn level to the activity log — the deferred middle of ACE-008's
thread_id(conversation) ▸correlation_id(turn) ▸ step. One user question fans out into N agent sub-queries; this binds them, so the admin Sessions drawer reads "User asked X → 2 queries". Grounded in real data (a meridian session showed the gap and that Claude driftsuser_questiononto later refinements).Changes
correlation_id— migration009adds the nullable column;ToolCallRecord+ the DB sink +_TOOL_CALL_COLScarry it;record_tool_callcapturesargs.get("correlation_id").execute_sql'sinputSchemagains acorrelation_idparam, andSERVER_INSTRUCTIONSnow tells Claude to keepuser_questionverbatim across a turn (refinement goes only inraw_query) and mint onecorrelation_idper user question. (The server can't mint it — the MCP protocol carries no turn boundary.)model_store._group_turnsfolds a session's calls into turns bycorrelation_id; the turn's question is the earliest call'suser_question(drift-proof); a call with nocorrelation_idis its own singleton turn._session_drawerrenders one "User asked … · N queries" block per turn with each refinement'sagent_query+ SQL.Safety / degradation
Best-effort + graceful: no
correlation_id→ reads like the old flat list, never errors. Read-only + admin-gated; every self-reported field escaped;correlation_idis never rendered into HTML (used only as a grouping key); no new egress.Test plan
tests/test_admin_activity.py:correlation_idround-trips; theinputSchemaexposes it;SERVER_INSTRUCTIONScarries the verbatim + per-turn guidance; turns group bycorrelation_id; the drift case (2nd call's question differs → earliest wins); degradation (nocorrelation_id→ singleton turns); the drawer renders "User asked" + bothagent_queryrefinements; the existing XSS-escape test still covers the sessions tab.Checklist
uv run dev.py checkgreen — 953 tests, ruff, gitleaksuv run dev.py cover)/code-review(2 finder angles) — 0 findings; Agami rubric 0 must-fixcorrelation_idvia the live Claude connection)