mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-05-21 10:23:36 +00:00
Patrol's "patrol-main" session was reused across every scheduled run, so ExecutePatrolStream loaded the full session history into the agentic loop's input. When any prior run ended after the model emitted tool_calls but before all tool results landed (provider error, timeout, context cancellation), the orphan tool_calls were persisted and every subsequent run inherited them. The provider then rejected the conversation with: An assistant message with 'tool_calls' must be followed by tool messages responding to each 'tool_call_id'. (insufficient tool messages following tool_calls message) Patrol failed 271 consecutive runs with this error before it was diagnosed. Each new run added another user prompt on top of the broken structure, so the message slice grew to 33+ messages with one assistant turn at position 23 holding 4 orphan tool_call_ids and 9 user prompts stacked after it. The "patrol runs need a clean slate" comment at line 1898 documents that the knowledge accumulator is freshened per run; the conversation history was the matching gap. ExecutePatrolStream now passes only this run's user prompt to the agentic loop. The session is still written to for audit/forensics, just no longer fed back into the model. Live verified: Patrol now completes successfully (18 tool calls, 3m23s) on a session that previously failed every run with the malformed-history error. The runtime-failure finding auto-resolved on this same successful run. Adds a classifier bucket for "insufficient tool messages" errors so any future regression in this area surfaces with a meaningful diagnostic instead of the generic "Provider analysis error" fallback. New PatrolFailureCauseMalformedToolHistory cause; predicate patrolMalformedToolHistory matches DeepSeek's exact phrasing and OpenAI's similar variants. ai-runtime contract updated. |
||
|---|---|---|
| .. | ||
| internal | ||
| v6 | ||
| control_plane.json | ||
| control_plane.schema.json | ||