Environment
- exo official app 1.0.71 (also present in
main @ b5375f8c: src/exo/api/types/claude_api.py → ClaudeRole = Literal["user", "assistant"])
- Client: Claude Code 2.1.169 pointed at exo via
ANTHROPIC_BASE_URL=http://<node>:52415
Symptom
Claude Code fails on its first request:
API Error: 422 {"detail":[{"type":"literal_error","loc":["body","messages",1,"role"],
"msg":"Input should be 'user' or 'assistant'","input":"system", ...}]}
Minimal repro without Claude Code:
curl -s http://localhost:52415/v1/messages \
-H 'Content-Type: application/json' -H 'anthropic-version: 2023-06-01' \
-d '{"model":"<loaded-model>","max_tokens":32,
"messages":[{"role":"user","content":"hi"},{"role":"system","content":"be brief"}]}'
Discussion
Strictly, Anthropic's Messages API only allows user/assistant in messages (system prompt goes in the top-level system field). In practice, though, real-world Anthropic-format clients — including Claude Code, the most common reason people set ANTHROPIC_BASE_URL to an exo node — do send system-role entries inside messages, so exo's strict Literal["user","assistant"] makes the endpoint unusable for exactly the clients it exists for.
A lenient adapter behavior would make /v1/messages practically useful: accept "system" in ClaudeRole and fold such messages into the system prompt (prepend to the top-level system value) before conversion, as other Anthropic-compatible servers do.
Happy to send a PR if this direction is acceptable.
Environment
main@b5375f8c:src/exo/api/types/claude_api.py→ClaudeRole = Literal["user", "assistant"])ANTHROPIC_BASE_URL=http://<node>:52415Symptom
Claude Code fails on its first request:
Minimal repro without Claude Code:
Discussion
Strictly, Anthropic's Messages API only allows
user/assistantinmessages(system prompt goes in the top-levelsystemfield). In practice, though, real-world Anthropic-format clients — including Claude Code, the most common reason people setANTHROPIC_BASE_URLto an exo node — do sendsystem-role entries insidemessages, so exo's strictLiteral["user","assistant"]makes the endpoint unusable for exactly the clients it exists for.A lenient adapter behavior would make
/v1/messagespractically useful: accept"system"inClaudeRoleand fold such messages into the system prompt (prepend to the top-levelsystemvalue) before conversion, as other Anthropic-compatible servers do.Happy to send a PR if this direction is acceptable.