{"repo":"NousResearch/hermes-agent","public_id":"31435","display_label":"Tool result content coerced to string for API compliance","summary":"Multiple fixes addressing a bug where tool/plugin results returned as dicts or non-string types were sent raw to OpenAI-compatible providers, causing HTTP 400 errors. Changes enforce that role=tool message content is serialized to a string before transmission.","subsystem":"agent","counts":{"members":7,"open_issues":1,"open_issues_distinct":1,"open_prs":0,"closed_issues":1,"merged_prs":1,"attempt_prs":4},"landed_fix":{"status":"merged_to_main","basis":"structural","pr":61787,"merged_at":"2026-07-10T04:32:01+00:00"},"resolution":{"state":"unresolved","by":null},"freshness":{"state":"verified","last_verified_at":"2026-07-10T04:32:01+00:00","is_stale":false},"grouping":{"backbone":"STRUCTURAL_SPANNING","link_density":0.3028571428571429},"fix_edges":[{"issue_number":31435,"pr_number":61787,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false,"pr_merged_at":"2026-07-10T04:32:01+00:00"}],"members":[{"kind":"issue","number":31435,"title":"tool message content must be string: plugin tools returning dict cause upstream 400 (Z.ai error 1210, OpenAI/Manifest fallback_exhausted)","url":null,"state":"closed"},{"kind":"issue","number":48244,"title":"Dict tool results sent as raw JSON object → OpenAI-compatible providers reject (HTTP 400 / GLM 1210), exhausting fallback","url":null,"state":"open"},{"kind":"pr","number":31459,"title":"fix: coerce role=tool message content to string (workflow-engine + defensive sanitizer)","url":null,"state":"closed","close_reason":{"category":"uncategorized","implication":"needs_llm"},"merged":false,"is_fix_pr":true,"fix_tier":"suggested","fix_detail_withheld":true},{"kind":"pr","number":31770,"title":"fix(agent): coerce tool-result content to string for OpenAI wire format","url":null,"state":"closed","close_reason":{"refs":[{"kind":"commit","value":"f8361d29c8e2a2be6ba9ada32f1d694bf47a4b6a","number":0},{"kind":"pr","value":"#61787","number":61787}],"category":"implemented_elsewhere","implication":"superseded"},"merged":false},{"kind":"pr","number":48354,"title":"fix(agent): coerce non-string tool result content to JSON (#48244)","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#31770","number":31770},{"kind":"pr","value":"#48244","number":48244},{"kind":"pr","value":"#31435","number":31435}],"category":"merged_via","implication":"superseded"},"merged":false},{"kind":"pr","number":51671,"title":"fix(agent,cli): tool message spec compliance and callable entry point handling","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#48244","number":48244}],"category":"volume_quota","implication":"active"},"merged":false},{"kind":"pr","number":61787,"title":"fix(tools): enforce registry result contract","url":null,"state":"merged","close_reason":{"category":"merged"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":["tests/tools/test_registry.py","tools/registry.py"]}],"trust":{"default_tier":"verified","includes_suggested":false}}