The Anthropic API — :anthropic¶
LM Studio serves Anthropic's Messages API at POST /v1/messages, so a codebase
written against Claude can point at a local model without changing how it
talks:
RubyLLM.configure { |config| config.lms_protocol = :anthropic }
chat = RubyLLM.chat(model: 'qwen/qwen3-4b', provider: :lms)
chat.ask('Hello').raw.body
# => {"id" => "msg_...", "type" => "message", "role" => "assistant",
# "content" => [{"type" => "text", "text" => "..."}],
# "stop_reason" => "end_turn",
# "usage" => {"input_tokens" => 18, "output_tokens" => 25, ...}}
RubyLLM's stock Anthropic protocol drives it unchanged apart from the request
path. LM Studio wants no credentials and no anthropic-version header.
What works¶
- Plain exchanges
- Streaming, with proper
message_start/content_block_deltaSSE events - Tool calls:
tool_useblocks withstop_reason: "tool_use", executed as ordinaryRubyLLM::Toolobjects in your process - Reasoning:
with_thinking(effort: :low)puts Anthropic'sthinkingrequest field on the wire, LM Studio honors it, and the reasoning comes back as athinkingcontent block inresponse.thinking.text;with_thinking(false)turns it off. Anthropic's usage block carries no reasoning token count, soresponse.tokens.thinkingisnilhere. Verified on LM Studio 0.4.26.
What doesn't¶
with_schema is ignored, quietly
LM Studio ignores the schema and nothing raises. The same model and schema, two protocols:
# :chat_completions => {"name": "John", "age": 30}
# :anthropic => "Understood. John is 30 years old. How can I help..."
Use :chat_completions for structured output.
Embeddings and judgments are unaffected: they always go to their own endpoints.
Example 12_anthropic_protocol.rb shows streaming, tools and the with_schema
trap side by side.