Commit ab41b11
authored
fix(email): stop the assistant from narrating what the turn's tools don't support (#2659)
The email agent used to say things its own tools hadn't earned: a
confident "archived" or "starred" with zero tool calls that turn, a
pre-scan claiming "no urgent or actionable items" while its own scan
result held some, unread counts described as spanning "across your
connected mailboxes" when the number is per-INBOX-scoped, and internal
payload scaffolding — a `[shown to the user]` marker,
`[suggested_archives]`-style field names, raw provider ids, undecoded
`\uXXXX` escapes — leaking into replies instead of being summarized. It
now either backs a claim with a matching tool call from that same turn,
or replaces the claim with an honest, data-grounded fallback;
`check_followups` also returns an explicit `count` so a long list has
nothing left to miscount.
Root cause for the unicode leak: every `json.dumps` call in the shared
agent loop (`src/gaia/agents/base/agent.py`) that builds model-visible
tool-result text was missing `ensure_ascii=False`, so non-ASCII
characters escaped as literal `\uXXXX` text — and could inflate a
payload's measured length enough to trigger truncation it didn't need.
Fixed at every call site there, which benefits every agent built on the
shared loop, not just email; the blast-radius check (`tests/unit/ -k
"agent_loop or tool_result or truncat"`) is green.
This PR also now folds in #2656's calendar-conflict grounding (merged to
main after this branch), which independently added the same kind of
check — a post-hoc verdict the model narrated without actually calling
`detect_calendar_conflicts` — but wired as a second, separate pass over
the final answer. Left as two passes, one turn could get two independent
disclaimers appended to a single reply, so the calendar check now lives
in this PR's shared `answer_grounding.py` framework as one more rule,
behind the same single hook.
## Test plan
- [x] `PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring
.venv/bin/python -m pytest tests/unit/agents/email/ tests/unit/email/
hub/agents/email/python/tests/ -q` — 2414 passed
- [x] `PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring
.venv/bin/python -m pytest tests/unit/ -q -k "agent_loop or tool_result
or truncat"` — 100 passed, 0 failed (proves the shared-loop unicode fix
doesn't regress other agents)
- [x] `go build ./... && go test ./...` in `tui/` — all packages green
- [x] `python util/lint.py --all` — all checks pass (MyPy warnings
pre-existing, non-blocking)
- [x] Every guard function mutation-tested, including the newly-folded
calendar-conflict rule: revert the fix alone, confirm its test fails,
restore, confirm green again
- [x] Dedicated composition test proves the calendar-conflict and
attention-card checks — both append-only and independent — fire together
on the same turn rather than one short-circuiting the other
- [ ] Dispatcher: 3 fresh-process `check_followups` runs against a
22-item mailbox (#2622 AC2), a 10+-turn TUI session reproducing the
empty-tool-trace narration (#2621 AC1), both capturing the trailing "N
steps · N tools" line
Closes #2621
Closes #2622
Closes #2636
Closes #26371 parent 7a93bfb commit ab41b11
14 files changed
Lines changed: 1872 additions & 117 deletions
File tree
- hub/agents/email/python
- gaia_agent_email
- tools
- tests
- src/gaia/agents/base
- tests/unit/agents
- tui/internal/client
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
103 | 103 | | |
104 | 104 | | |
105 | 105 | | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
106 | 155 | | |
107 | 156 | | |
108 | 157 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
45 | 45 | | |
46 | 46 | | |
47 | 47 | | |
| 48 | + | |
48 | 49 | | |
49 | 50 | | |
50 | 51 | | |
| |||
61 | 62 | | |
62 | 63 | | |
63 | 64 | | |
64 | | - | |
65 | | - | |
66 | | - | |
67 | | - | |
68 | | - | |
69 | | - | |
| 65 | + | |
70 | 66 | | |
71 | 67 | | |
72 | 68 | | |
| |||
221 | 217 | | |
222 | 218 | | |
223 | 219 | | |
224 | | - | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
225 | 225 | | |
226 | 226 | | |
227 | 227 | | |
| |||
279 | 279 | | |
280 | 280 | | |
281 | 281 | | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
282 | 293 | | |
283 | 294 | | |
284 | 295 | | |
| |||
308 | 319 | | |
309 | 320 | | |
310 | 321 | | |
311 | | - | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
312 | 331 | | |
313 | 332 | | |
314 | 333 | | |
| |||
405 | 424 | | |
406 | 425 | | |
407 | 426 | | |
408 | | - | |
409 | | - | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
410 | 437 | | |
411 | 438 | | |
412 | 439 | | |
| |||
460 | 487 | | |
461 | 488 | | |
462 | 489 | | |
463 | | - | |
464 | | - | |
465 | | - | |
466 | | - | |
467 | | - | |
468 | | - | |
469 | | - | |
470 | | - | |
471 | | - | |
472 | | - | |
473 | | - | |
474 | | - | |
475 | | - | |
476 | | - | |
477 | | - | |
478 | | - | |
479 | | - | |
480 | | - | |
481 | 490 | | |
482 | 491 | | |
483 | 492 | | |
| |||
1019 | 1028 | | |
1020 | 1029 | | |
1021 | 1030 | | |
1022 | | - | |
1023 | | - | |
1024 | | - | |
1025 | | - | |
1026 | | - | |
1027 | | - | |
1028 | | - | |
1029 | | - | |
1030 | | - | |
1031 | | - | |
1032 | | - | |
| 1031 | + | |
| 1032 | + | |
| 1033 | + | |
| 1034 | + | |
| 1035 | + | |
| 1036 | + | |
1033 | 1037 | | |
1034 | 1038 | | |
1035 | 1039 | | |
| |||
0 commit comments