TL;DR
Current output (what reaches the provider when an agent has instructions + one defineInstructions/defineDynamic, and the user message carries a file part):
Expected output (system messages merged at the model-call boundary; history/lifecycle unchanged):
What problem are you trying to solve?
eve assembles the model-call instructions as an array of system messages: prepareModelCallInput (harness/tool-loop) builds [agent.system, ...dynamic instruction messages, skill announcements, delivery note]. Any agent that combines defineAgent({ instructions }) with one defineInstructions/defineDynamic therefore sends two or more system-role messages on every call.
Fireworks' OpenAI-compatible chat completions endpoint (observed on accounts/fireworks/models/qwen3p7-plus, eve 0.21.1 via @ai-sdk/fireworks) returns an opaque HTTP 500 when a request combines 2+ system messages with array-form user content. Each half of the pattern works alone: one system message + array user content is fine, multiple system messages + plain string user content is fine. The intersection fails deterministically. We've verified this is a Fireworks server-side bug and reported it to them separately — but eve emits the triggering pattern by design, and nothing about the semantics requires N separate system messages.
This is about to hit more people: eve 0.21's native attachment lane produces array-form user content whenever a message carries file parts, so "agent with dynamic instructions + user sends an attachment" = every turn fails with MODEL_CALL_FAILED on Fireworks-hosted models.
Repro sketch:
defineAgent({ model: fireworks('accounts/fireworks/models/qwen3p7-plus'), instructions }) plus any defineInstructions/defineDynamic (→ 2 system messages).
- Send a turn whose user message has array content (e.g. a file part).
- Provider returns 500; turn parks with
MODEL_CALL_FAILED.
Workaround we're running: a LanguageModelMiddleware whose transformParams concatenates all system messages into one (join('\n\n')). No behavioral difference observed — which supports merging being semantically safe.
Proposed solution
Merge the assembled system messages into a single system message at the model-call boundary (prepareModelCallInput), keeping them separate in session history and in the dynamic-instruction lifecycle. For OpenAI-compatible APIs the concatenation is semantically equivalent; Anthropic handles system separately anyway. The applySystemCacheBreakpoint logic would apply to the merged message. If unconditional merging feels too opinionated, an agent-level opt-in (e.g. mergeSystemMessages: true) would do — but defensive-by-default seems right given providers demonstrably choke on the pattern.
TL;DR
Current output (what reaches the provider when an agent has
instructions+ onedefineInstructions/defineDynamic, and the user message carries a file part):[ { "role": "system", "content": "<agent instructions>" }, { "role": "system", "content": "<dynamic instructions>" }, { "role": "user", "content": [ { "type": "text", "text": "What's my P&L for 2025?" }, { "type": "file", "filename": "receipt.jpg", "mediaType": "image/jpeg", "...": "..." } ] } ] // Fireworks → HTTP 500 (opaque), turn parks with MODEL_CALL_FAILEDExpected output (system messages merged at the model-call boundary; history/lifecycle unchanged):
[ { "role": "system", "content": "<agent instructions>\n\n<dynamic instructions>" }, { "role": "user", "content": [ { "type": "text", "text": "What's my P&L for 2025?" }, { "type": "file", "filename": "receipt.jpg", "mediaType": "image/jpeg", "...": "..." } ] } ] // Fireworks → 200What problem are you trying to solve?
eve assembles the model-call
instructionsas an array of system messages:prepareModelCallInput(harness/tool-loop) builds[agent.system, ...dynamic instruction messages, skill announcements, delivery note]. Any agent that combinesdefineAgent({ instructions })with onedefineInstructions/defineDynamictherefore sends two or more system-role messages on every call.Fireworks' OpenAI-compatible chat completions endpoint (observed on
accounts/fireworks/models/qwen3p7-plus, eve 0.21.1 via@ai-sdk/fireworks) returns an opaque HTTP 500 when a request combines 2+ system messages with array-form user content. Each half of the pattern works alone: one system message + array user content is fine, multiple system messages + plain string user content is fine. The intersection fails deterministically. We've verified this is a Fireworks server-side bug and reported it to them separately — but eve emits the triggering pattern by design, and nothing about the semantics requires N separate system messages.This is about to hit more people: eve 0.21's native attachment lane produces array-form user content whenever a message carries file parts, so "agent with dynamic instructions + user sends an attachment" = every turn fails with
MODEL_CALL_FAILEDon Fireworks-hosted models.Repro sketch:
defineAgent({ model: fireworks('accounts/fireworks/models/qwen3p7-plus'), instructions })plus anydefineInstructions/defineDynamic(→ 2 system messages).MODEL_CALL_FAILED.Workaround we're running: a
LanguageModelMiddlewarewhosetransformParamsconcatenates all system messages into one (join('\n\n')). No behavioral difference observed — which supports merging being semantically safe.Proposed solution
Merge the assembled system messages into a single system message at the model-call boundary (
prepareModelCallInput), keeping them separate in session history and in the dynamic-instruction lifecycle. For OpenAI-compatible APIs the concatenation is semantically equivalent; Anthropic handlessystemseparately anyway. TheapplySystemCacheBreakpointlogic would apply to the merged message. If unconditional merging feels too opinionated, an agent-level opt-in (e.g.mergeSystemMessages: true) would do — but defensive-by-default seems right given providers demonstrably choke on the pattern.