Skip to content

chat/send: allow null message on tool_call_results path#188

Merged
jeffdafoe merged 1 commit into
mainfrom
fix/chat-send-allow-no-message-with-tool-results
May 8, 2026
Merged

chat/send: allow null message on tool_call_results path#188
jeffdafoe merged 1 commit into
mainfrom
fix/chat-send-allow-no-message-with-tool-results

Conversation

@jeffdafoe
Copy link
Copy Markdown
Owner

Summary

  • Fixes a service-layer regression deployed in 57c4c32: every salem-engine request using the new tool_call_results / persist_only body shape (introduced for parallel tool calls) was rejected with 400 BAD_REQUEST: Required fields: from_agent, message.
  • Splits the combined fromAgent/message guard and only requires message when toolCallResults is null. Route already enforces mutual exclusivity, so the tool-results path is safe — rowSpecs uses spec.message from each tool-result entry, and handleDirectChat's tool-use branch builds the user message from history rather than dereferencing the inline messageText.

Impact

NPC ticks and chronicler harness are entirely broken in production right now (every iter=1 + every persistToolResults call returns 400). Confirmed via salem journalctl: chronicler dispatch, agent ticks, terminal commits all dying with this error since the deploy at 22:16 UTC.

Test plan

  • Diff inspection: confirmed no downstream null-deref of outer message on the tool-results path
  • Deploy to VPS, watch journalctl -u salem-engine for the 400 errors to stop
  • Trigger an NPC tick (PC knock at a shop) and verify a done row lands in agent_action_log
  • Verify chronicler dispatch round-trips cleanly (next dusk-phase boundary)

— Home

🤖 Generated with Claude Code

Pairs with 57c4c32 — that commit added route-level acceptance of the
parallel-tool-call body shape (tool_call_results + persist_only with no
message), but left the service-layer guard requiring message to be
non-null. Result: every salem-engine request using the new shape was
rejected with 400 BAD_REQUEST: Required fields: from_agent, message,
killing every NPC tick at iter=1 and the chronicler harness too.

Split the combined fromAgent/message guard into two and gate the
message check on toolCallResults being null. Route already enforces
mutual exclusivity between message and tool_call_results, so allowing
message=null on the tool-results path is safe — rowSpecs uses
spec.message from each tool-result entry, and handleDirectChat's
tool-use branch builds the user message from history rather than
dereferencing the inline messageText.

Co-Authored-By: Home <noreply@anthropic.com>
@jeffdafoe jeffdafoe merged commit e3028d5 into main May 8, 2026
6 checks passed
@jeffdafoe jeffdafoe deleted the fix/chat-send-allow-no-message-with-tool-results branch May 8, 2026 23:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant