### Install dependencies and CLI Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/spec/README.md Commands for setting up the development environment and required external tools. ```bash bundle install ``` ```bash npm install -g @anthropic-ai/claude-code ``` ```bash which claude claude -v ``` -------------------------------- ### Install OTel gems Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/README.md Install the necessary OpenTelemetry gems for observability. ```bash gem install opentelemetry-sdk opentelemetry-exporter-otlp ``` -------------------------------- ### Install Dependencies Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/CLAUDE.md Use this command to install project dependencies via Bundler. ```bash bundle install ``` -------------------------------- ### Test SDK tools Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/spec/README.md Example of creating a tool and an MCP server instance for testing tool execution logic. ```ruby tool = ClaudeAgentSDK.create_tool('test_tool', 'Description', { arg: :string }) do |args| { content: [{ type: 'text', text: "Result: #{args[:arg]}" }] } end server = ClaudeAgentSDK.create_sdk_mcp_server( name: 'test_server', tools: [tool] ) result = server[:instance].call_tool('test_tool', { arg: 'value' }) ``` -------------------------------- ### Install Claude Agent SDK (Ruby) Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/README.md Add the SDK to your Gemfile for either the latest GitHub version or a stable release. Then, execute bundle install. ```ruby gem 'claude-agent-sdk', github: 'ya-luotao/claude-agent-sdk-ruby' ``` ```ruby gem 'claude-agent-sdk', '~> 0.14.1' ``` -------------------------------- ### Install Claude Agent SDK (Bash) Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/README.md Install the SDK directly from RubyGems using the gem install command. ```bash bundle install ``` ```bash gem install claude-agent-sdk ``` -------------------------------- ### Define and Mount an SDK MCP Server Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/plugins/claude-agent-ruby/skills/claude-agent-ruby/references/mcp-servers.md Define a tool as a Ruby proc/lambda and mount it as an SDK MCP server. This example demonstrates creating a 'greet' tool and integrating it into the agent's options. ```ruby require "claude_agent_sdk" require "async" greet_tool = ClaudeAgentSDK.create_tool("greet", "Greet a user", { name: :string }) do |args| { content: [{ type: "text", text: "Hello, #{args[:name]}!" }] } end server = ClaudeAgentSDK.create_sdk_mcp_server( name: "tools", version: "1.0.0", tools: [greet_tool] ) options = ClaudeAgentSDK::ClaudeAgentOptions.new( mcp_servers: { tools: server }, allowed_tools: ["mcp__tools__greet"] ) Async do client = ClaudeAgentSDK::Client.new(options: options) client.connect client.query("Greet Alice") client.receive_response { |msg| puts msg.inspect } ensure client&.disconnect end.wait ``` -------------------------------- ### Quick Start: Basic Query (Ruby) Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/README.md Perform a simple query to Claude Code using the query() function and print the response. ```ruby require 'claude_agent_sdk' ClaudeAgentSDK.query(prompt: "What is 2 + 2?") do |message| puts message end ``` -------------------------------- ### Interactive Client Setup and Usage Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/plugins/claude-agent-ruby/skills/claude-agent-ruby/references/usage-map.md Establishes an interactive client connection, sends a query, and receives responses asynchronously. Requires 'claude-agent-sdk' and 'async' gems. ```ruby require 'claude_agent_sdk' require 'async' Async do client = ClaudeAgentSDK::Client.new client.connect client.query("Hello") client.receive_response { |msg| puts msg } client.disconnect end.wait ``` -------------------------------- ### Locate gem installation path Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/skills/references/usage-map.md Commands to find the local installation directory of the gem for documentation access. ```bash bundle show claude-agent-sdk ``` ```bash ruby -e 'puts Gem::Specification.find_by_name("claude-agent-sdk").full_gem_path' ``` -------------------------------- ### Add and Install Claude Code Skill (Bash) Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/README.md Add the Claude Agent SDK as a marketplace and then install the corresponding skill for Claude Code. ```bash # Add the marketplace /plugin marketplace add ya-luotao/claude-agent-sdk-ruby # Install the plugin /plugin install claude-agent-ruby@claude-agent-sdk-ruby ``` -------------------------------- ### Define and Use Custom Tool with SDK MCP Server Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/IMPLEMENTATION.md Example demonstrating how to define a custom tool ('add') and integrate it with the SDK MCP server for use with Claude. Requires ClaudeAgentSDK and ClaudeAgentOptions. ```ruby # Define a tool add_tool = ClaudeAgentSDK.create_tool('add', 'Add numbers', { a: :number, b: :number }) do |args| result = args[:a] + args[:b] { content: [{ type: 'text', text: "Result: #{result}" }] } end # Create server server = ClaudeAgentSDK.create_sdk_mcp_server(name: 'calc', tools: [add_tool]) # Use with Claude options = ClaudeAgentOptions.new( mcp_servers: { calc: server }, allowed_tools: ['mcp__calc__add'] ) ``` -------------------------------- ### SDK MCP Tool with No Parameters Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/plugins/claude-agent-ruby/skills/claude-agent-ruby/references/usage-map.md Defines a simple SDK MCP tool that requires no arguments. This example creates a 'ping' tool that responds with 'pong'. ```ruby tool = ClaudeAgentSDK.create_tool('ping', 'Ping the server', {}) do |_args| { content: [{ type: 'text', text: 'pong' }] } end ``` -------------------------------- ### Claude Agent Ruby SDK - Overview and Decision Guide Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/skills/SKILL.md Provides an overview of the Claude Agent Ruby SDK and a decision guide for choosing the appropriate method for different use cases. ```APIDOC ## Claude Agent Ruby SDK ### Overview Use this skill to build or refactor Ruby integrations with Claude Code via `claude-agent-sdk`, favoring the gem's README and types for exact APIs. ### Decision Guide - Choose `ClaudeAgentSDK.query` for one-shot queries or streaming input. Internally uses the control protocol (streaming mode). - Choose `ClaudeAgentSDK::Client` for multi-turn sessions, hooks, permission callbacks, MCP server control, or dynamic model switching; wrap in `Async do ... end.wait`. - Choose SDK MCP servers (`create_tool`, `create_sdk_mcp_server`) for in-process tools; choose external MCP configs for subprocess/HTTP servers. - Choose `ClaudeAgentSDK.list_sessions` / `ClaudeAgentSDK.get_session_messages` for browsing previous session transcripts (pure filesystem, no CLI needed). ``` -------------------------------- ### Configure External HTTP MCP Server Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/plugins/claude-agent-ruby/skills/claude-agent-ruby/references/mcp-servers.md Configure an external HTTP MCP server by providing its URL and authentication headers. This example uses environment variables for sensitive information. ```ruby mcp_servers = { "api_tools" => ClaudeAgentSDK::McpHttpServerConfig.new( url: ENV.fetch("MCP_SERVER_URL"), headers: { "Authorization" => "Bearer #{ENV.fetch("MCP_TOKEN")}" } ).to_h } options = ClaudeAgentSDK::ClaudeAgentOptions.new( mcp_servers: mcp_servers, permission_mode: "bypassPermissions" ) ``` -------------------------------- ### Advanced Client Features in Ruby Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/README.md Shows how to use advanced client features like sending interrupt signals, changing permission modes and AI models, and managing MCP servers. This example requires an active Async context. ```ruby Async do client = ClaudeAgentSDK::Client.new client.connect # Send interrupt signal client.interrupt # Change permission mode during conversation client.set_permission_mode('acceptEdits') # Change AI model during conversation client.set_model('claude-sonnet-4-5') # Get MCP server connection status status = client.get_mcp_status puts "MCP status: #{status}" # Get server initialization info info = client.get_server_info puts "Available commands: #{info}" # Reconnect a failed MCP server client.reconnect_mcp_server('my-server') # Enable or disable an MCP server client.toggle_mcp_server('my-server', false) # Stop a running background task client.stop_task('task_abc123') client.disconnect end.wait ``` -------------------------------- ### Thinking Configuration: Custom Budget Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/plugins/claude-agent-ruby/skills/claude-agent-ruby/references/usage-map.md Sets a custom budget for thinking tokens, allowing fine-grained control over resource usage. This example sets the budget to 10,000 tokens. ```ruby options = ClaudeAgentSDK::ClaudeAgentOptions.new( thinking: ClaudeAgentSDK::ThinkingConfigEnabled.new(budget_tokens: 10_000) ) ``` -------------------------------- ### Configure HTTP MCP Servers in Ruby Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/README.md Configure HTTP MCP servers to connect to remote tool services. This example sets up a configuration with a URL and authorization headers, using environment variables for sensitive information. ```ruby mcp_servers = { 'api_tools' => ClaudeAgentSDK::McpHttpServerConfig.new( url: ENV['MCP_SERVER_URL'], headers: { 'Authorization' => "Bearer #{ENV['MCP_TOKEN']}" } ).to_h } options = ClaudeAgentSDK::ClaudeAgentOptions.new( mcp_servers: mcp_servers, permission_mode: 'bypassPermissions' ) ``` -------------------------------- ### Define Custom Tool Permissions in Ruby Source: https://context7.com/ya-luotao/claude-agent-sdk-ruby/llms.txt Implement a permission callback to control tool usage. This example allows 'Read' operations, denies writing to sensitive directories, and modifies 'Bash' commands. ```ruby permission_callback = lambda do |tool_name, input, context| # Allow all Read operations if tool_name == 'Read' return ClaudeAgentSDK::PermissionResultAllow.new end # Block Write to sensitive directories if tool_name == 'Write' file_path = input[:file_path] || input['file_path'] || '' sensitive_dirs = ['/etc/', '/usr/', '/var/', '~/.ssh/'] sensitive_dirs.each do |dir| if file_path.include?(dir) return ClaudeAgentSDK::PermissionResultDeny.new( message: "Cannot write to protected directory: #{dir}", interrupt: false ) end end return ClaudeAgentSDK::PermissionResultAllow.new end # Modify Bash commands to add safety flags if tool_name == 'Bash' modified_input = input.dup modified_input[:command] = "set -e; #{input[:command]}" return ClaudeAgentSDK::PermissionResultAllow.new(updated_input: modified_input) end ClaudeAgentSDK::PermissionResultAllow.new end options = ClaudeAgentSDK::ClaudeAgentOptions.new( allowed_tools: ['Read', 'Write', 'Bash'], can_use_tool: permission_callback ) Async do client = ClaudeAgentSDK::Client.new(options: options) client.connect client.query("Create a config.txt file in /tmp with some content") client.receive_response { |msg| puts msg.inspect } client.disconnect end.wait ``` -------------------------------- ### Handle SDK Exceptions in Ruby Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/README.md Use a begin-rescue block to catch specific Claude Agent SDK errors like timeouts, CLI not found, or process failures. Ensure necessary setup with 'require "claude_agent_sdk"'. ```ruby require 'claude_agent_sdk' begin ClaudeAgentSDK.query(prompt: "Hello") do |message| puts message end rescue ClaudeAgentSDK::ControlRequestTimeoutError puts "Control protocol timed out — consider increasing the timeout" rescue ClaudeAgentSDK::CLINotFoundError puts "Please install Claude Code" rescue ClaudeAgentSDK::ProcessError => e puts "Process failed with exit code: #{e.exit_code}" rescue ClaudeAgentSDK::CLIJSONDecodeError => e puts "Failed to parse response: #{e}" end ``` -------------------------------- ### Create and Use SDK MCP Server with Tools Source: https://context7.com/ya-luotao/claude-agent-sdk-ruby/llms.txt Demonstrates creating an SDK MCP server with tools and then using it with a client to send a query. ```ruby calculator_server = ClaudeAgentSDK.create_sdk_mcp_server( name: 'calculator', version: '1.0.0', tools: [greet_tool, divide_tool] ) # Use with Client options = ClaudeAgentSDK::ClaudeAgentOptions.new( mcp_servers: { calc: calculator_server }, allowed_tools: ['mcp__calc__greet', 'mcp__calc__divide'] ) Async do client = ClaudeAgentSDK::Client.new(options: options) client.connect client.query("Greet Alice and then divide 100 by 4") client.receive_response { |msg| puts msg.inspect } client.disconnect end.wait ``` -------------------------------- ### Bare Mode Configuration and Query Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/plugins/claude-agent-ruby/skills/claude-agent-ruby/references/usage-map.md Initializes the SDK in bare mode with custom system prompts and directory additions for minimal startup. Use this for specific environments or reduced overhead. ```ruby options = ClaudeAgentSDK::ClaudeAgentOptions.new( bare: true, system_prompt: 'You are a helpful assistant.', add_dirs: ['/path/to/project'], permission_mode: 'bypassPermissions' ) ClaudeAgentSDK.query(prompt: "Review this code", options: options) do |msg| puts msg if msg.is_a?(ClaudeAgentSDK::AssistantMessage) end ``` -------------------------------- ### Create SDK MCP Server with Resources and Prompts Source: https://context7.com/ya-luotao/claude-agent-sdk-ruby/llms.txt Shows how to create an SDK MCP server that includes both a resource for application settings and a prompt template for code review. ```ruby require 'claude_agent_sdk' require 'json' # Create a resource that Claude can read config_resource = ClaudeAgentSDK.create_resource( uri: 'config://app/settings', name: 'Application Settings', description: 'Current app configuration', mime_type: 'application/json' ) do config_data = { app_name: 'MyApp', version: '2.0.0', debug: false } { contents: [{ uri: 'config://app/settings', mimeType: 'application/json', text: JSON.pretty_generate(config_data) }] } end # Create a prompt template review_prompt = ClaudeAgentSDK.create_prompt( name: 'code_review', description: 'Review code for best practices', arguments: [ { name: 'code', description: 'Code to review', required: true }, { name: 'language', description: 'Programming language', required: false } ] ) do |args| { messages: [{ role: 'user', content: { type: 'text', text: "Review this #{args[:language] || 'code'} for best practices:\n\n#{args[:code]}" } }] } end # Create server with all capabilities dev_server = ClaudeAgentSDK.create_sdk_mcp_server( name: 'dev-tools', version: '1.0.0', tools: [], resources: [config_resource], prompts: [review_prompt] ) ``` -------------------------------- ### Basic Client Usage in Ruby Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/README.md Demonstrates how to initialize a client, connect, send a query, and receive responses, including handling assistant and result messages. Ensure to disconnect the client in a `ensure` block. ```ruby require 'claude_agent_sdk' require 'async' Async do client = ClaudeAgentSDK::Client.new begin # Connect automatically uses streaming mode for bidirectional communication client.connect # Send a query client.query("What is the capital of France?") # Receive the response client.receive_response do |msg| if msg.is_a?(ClaudeAgentSDK::AssistantMessage) msg.content.each do |block| puts block.text if block.is_a?(ClaudeAgentSDK::TextBlock) end elsif msg.is_a?(ClaudeAgentSDK::ResultMessage) puts "Cost: $#{msg.total_cost_usd}" if msg.total_cost_usd end end ensure client.disconnect end end.wait ``` -------------------------------- ### Initialize observer and run query Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/README.md Register the OTel observer and execute a query with the configured options. ```ruby require 'claude_agent_sdk' require 'claude_agent_sdk/instrumentation' observer = ClaudeAgentSDK::Instrumentation::OTelObserver.new( 'langfuse.session.id' => 'my-session-123', # optional: group traces by session 'user.id' => 'user-42' # optional: tag with user ID ) options = ClaudeAgentSDK::ClaudeAgentOptions.new( observers: [observer], allowed_tools: ['Bash', 'Read'], permission_mode: 'bypassPermissions' ) ClaudeAgentSDK.query(prompt: "List files in /tmp", options: options) do |msg| if msg.is_a?(ClaudeAgentSDK::AssistantMessage) msg.content.each do |block| puts block.text if block.is_a?(ClaudeAgentSDK::TextBlock) end end end # For long-running apps, flush before exit: # OpenTelemetry.tracer_provider.shutdown ``` -------------------------------- ### Get Session Messages Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/plugins/claude-agent-ruby/skills/claude-agent-ruby/references/options.md Retrieves the message transcript for a specific session. ```APIDOC ## GET /get_session_messages ### Description Fetches messages from a session transcript. ### Parameters #### Query Parameters - **session_id** (string) - Required - The unique identifier of the session. - **limit** (integer) - Optional - The maximum number of messages to return. ### Response #### Success Response (200) - **Array** - Returns an array of message objects containing: type, uuid, session_id, message, parent_tool_use_id. ``` -------------------------------- ### Configure Mixed MCP Servers Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/README.md Demonstrates how to combine internal SDK servers with external stdio-based MCP servers. ```ruby options = ClaudeAgentSDK::ClaudeAgentOptions.new( mcp_servers: { internal: sdk_server, # In-process SDK server external: { # External subprocess server type: 'stdio', command: 'external-server' } } ) ``` -------------------------------- ### Get Session Messages Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/skills/references/options.md Retrieves messages from a specific session transcript, with support for limiting the number of messages. ```APIDOC ## Get Session Messages ### Description Reads messages from a session transcript. ### Method N/A (SDK Function) ### Endpoint N/A (SDK Function) ### Parameters #### Query Parameters - **session_id** (String) - Required - The unique identifier of the session. - **limit** (Integer) - Optional - The maximum number of messages to retrieve. ### Response #### Success Response (200) - **Array** - An array of session message objects. - **type** (String) - The type of the message (e.g., 'user', 'assistant'). - **uuid** (String) - The unique identifier for the message. - **session_id** (String) - The ID of the session this message belongs to. - **message** (String) - The content of the message. - **parent_tool_use_id** (String) - The ID of the parent tool use, if applicable. ### Response Example ```json [ { "type": "user", "uuid": "msg-uuid-1", "session_id": "uuid-here", "message": "Hello, Claude!", "parent_tool_use_id": null }, { "type": "assistant", "uuid": "msg-uuid-2", "session_id": "uuid-here", "message": "Hi there! How can I help you today?", "parent_tool_use_id": null } ] ``` ``` -------------------------------- ### Initialize ClaudeAgentOptions in Bare Mode Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/plugins/claude-agent-ruby/skills/claude-agent-ruby/SKILL.md Use bare mode for minimal startup by skipping hooks and auto-discovery. Requires explicit configuration of system prompts and permissions. ```ruby options = ClaudeAgentSDK::ClaudeAgentOptions.new( bare: true, system_prompt: 'You are a code reviewer.', permission_mode: 'bypassPermissions' ) ``` -------------------------------- ### TaskStartedMessage Class Definition Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/README.md Represents a system message indicating a task has started. Inherits from SystemMessage and includes task-specific attributes. ```ruby # Typed subclasses (all inherit from SystemMessage, so is_a?(SystemMessage) still works) class TaskStartedMessage < SystemMessage attr_accessor :task_id, :description, :uuid, :session_id, :tool_use_id, :task_type end ``` -------------------------------- ### One-shot Query with Callback Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/plugins/claude-agent-ruby/skills/claude-agent-ruby/references/usage-map.md Perform a single query to the Claude API and process the response using a callback. Ensure the 'claude-agent-sdk' gem is installed. ```ruby require 'claude_agent_sdk' ClaudeAgentSDK.query(prompt: "Hello") { |msg| puts msg } ``` -------------------------------- ### Creating a Simple Tool in Ruby Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/README.md Demonstrates how to create a custom tool using `ClaudeAgentSDK.create_tool` with optional annotations and arguments. The tool is then registered with an SDK MCP server and used with the Claude client. Ensure the `async` gem is required. ```ruby require 'claude_agent_sdk' require 'async' # Define a tool using create_tool (with optional annotations) greet_tool = ClaudeAgentSDK.create_tool( 'greet', 'Greet a user', { name: :string }, annotations: { title: 'Greeter', readOnlyHint: true } ) do |args| { content: [{ type: 'text', text: "Hello, #{args[:name]}!" }] } end # Create an SDK MCP server server = ClaudeAgentSDK.create_sdk_mcp_server( name: 'my-tools', version: '1.0.0', tools: [greet_tool] ) # Use it with Claude options = ClaudeAgentSDK::ClaudeAgentOptions.new( mcp_servers: { tools: server }, allowed_tools: ['mcp__tools__greet'] ) Async do client = ClaudeAgentSDK::Client.new(options: options) client.connect client.query("Greet Alice") client.receive_response { |msg| puts msg } client.disconnect end.wait ``` -------------------------------- ### Stream Messages Dynamically in Ruby Source: https://context7.com/ya-luotao/claude-agent-sdk-ruby/llms.txt Send multiple messages during a single SDK session using streaming. Examples show creating streams from arrays and custom enumerators. ```ruby require 'claude_agent_sdk' # Create a stream from an array messages = ['Hello!', 'What is 2+2?', 'Thanks for the help!'] stream = ClaudeAgentSDK::Streaming.from_array(messages) ClaudeAgentSDK.query(prompt: stream) do |message| if message.is_a?(ClaudeAgentSDK::AssistantMessage) message.content.each do |block| puts block.text if block.is_a?(ClaudeAgentSDK::TextBlock) end end end # Create a custom streaming enumerator custom_stream = Enumerator.new do |yielder| yielder << ClaudeAgentSDK::Streaming.user_message("First: analyze this code") # ... do some processing yielder << ClaudeAgentSDK::Streaming.user_message("Now: suggest improvements") # ... more processing yielder << ClaudeAgentSDK::Streaming.user_message("Finally: write tests") end ClaudeAgentSDK.query(prompt: custom_stream) do |message| puts message.inspect end ``` -------------------------------- ### Basic Query in Python Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/IMPLEMENTATION.md Demonstrates a simple asynchronous query to the Claude API using the SDK. Requires the 'anyio' gem for running async code. ```python import anyio from claude_agent_sdk import query, ClaudeAgentOptions async def main(): async for message in query(prompt="Hello"): print(message) anyio.run(main) ``` -------------------------------- ### Implement Custom Observer in Ruby Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/README.md Implement the `Observer` module to build custom instrumentation for tracking messages and session closures. This example shows how to log cost and token usage. ```ruby class MyObserver include ClaudeAgentSDK::Observer def on_message(message) case message when ClaudeAgentSDK::ResultMessage puts "Cost: $#{message.total_cost_usd}, Tokens: #{message.usage}" end end def on_close puts "Session ended" end end options = ClaudeAgentSDK::ClaudeAgentOptions.new(observers: [MyObserver.new]) ``` -------------------------------- ### Configure Full Sandbox Environment Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/plugins/claude-agent-ruby/skills/claude-agent-ruby/references/usage-map.md Set up a comprehensive sandbox environment for the Claude agent, including network, filesystem, and violation handling. ```ruby sandbox = ClaudeAgentSDK::SandboxSettings.new( enabled: true, fail_if_unavailable: true, auto_allow_bash_if_sandboxed: true, network: ClaudeAgentSDK::SandboxNetworkConfig.new( allowed_domains: ['api.example.com', 'cdn.example.com'], allow_local_binding: true ), filesystem: ClaudeAgentSDK::SandboxFilesystemConfig.new( allow_write: ['/tmp/output'], deny_read: ['/etc/secrets'] ), ignore_violations: { 'network' => ['metrics.internal'] }, enable_weaker_network_isolation: false ) options = ClaudeAgentSDK::ClaudeAgentOptions.new( sandbox: sandbox, permission_mode: 'acceptEdits' ) ``` -------------------------------- ### Generate Structured JSON Output with Schema in Ruby Source: https://context7.com/ya-luotao/claude-agent-sdk-ruby/llms.txt Configure the SDK to output JSON based on a provided schema. This example defines a 'person_schema' and retrieves structured data from Claude. ```ruby require 'claude_agent_sdk' require 'json' # Define the JSON schema person_schema = { type: 'object', properties: { name: { type: 'string', description: 'Full name' }, age: { type: 'integer', minimum: 0 }, email: { type: 'string', format: 'email' }, skills: { type: 'array', items: { type: 'string' } }, address: { type: 'object', properties: { city: { type: 'string' }, country: { type: 'string' } }, required: ['city', 'country'] } }, required: ['name', 'age', 'skills'] } options = ClaudeAgentSDK::ClaudeAgentOptions.new( output_format: { type: 'json_schema', schema: person_schema }, max_turns: 3 ) structured_data = nil ClaudeAgentSDK.query( prompt: "Create a profile for a senior Ruby developer named Sarah in Berlin", options: options ) do |message| if message.is_a?(ClaudeAgentSDK::AssistantMessage) message.content.each do |block| if block.is_a?(ClaudeAgentSDK::ToolUseBlock) && block.name == 'StructuredOutput' structured_data = block.input end end end end if structured_data puts "Name: #{structured_data[:name]}" puts "Age: #{structured_data[:age]}" puts "Skills: #{structured_data[:skills].join(', ')}" puts "City: #{structured_data.dig(:address, :city)}" end ``` -------------------------------- ### Run Linter Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/CLAUDE.md Check code style and quality using RuboCop via Bundler. ```bash bundle exec rubocop ``` -------------------------------- ### Query with Options (Ruby) Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/README.md Perform a query with custom options, including setting a system prompt and limiting the number of turns. ```ruby # With options options = ClaudeAgentSDK::ClaudeAgentOptions.new( system_prompt: "You are a helpful assistant", max_turns: 1 ) ClaudeAgentSDK.query(prompt: "Tell me a joke", options: options) do |message| puts message end ``` -------------------------------- ### Stream Claude Responses in Rails with ActionCable Source: https://context7.com/ya-luotao/claude-agent-sdk-ruby/llms.txt Integrate Claude Agent SDK with Rails ActionCable to stream responses to the frontend in real-time. This example shows how to broadcast message chunks and completion status. ```ruby # config/initializers/claude_agent_sdk.rb require 'claude_agent_sdk/instrumentation' ClaudeAgentSDK.configure do |config| config.default_options = { permission_mode: 'bypassPermissions', observers: ENV['LANGFUSE_PUBLIC_KEY'].present? ? [ -> { ClaudeAgentSDK::Instrumentation::OTelObserver.new } ] : [] } end # app/jobs/chat_agent_job.rb class ChatAgentJob < ApplicationJob queue_as :claude_agents def perform(chat_id, message_content) Async do options = ClaudeAgentSDK::ClaudeAgentOptions.new( system_prompt: ClaudeAgentSDK::SystemPromptPreset.new( preset: 'claude_code', append: 'Be concise and helpful.' ), allowed_tools: ['Read', 'Grep', 'Glob'], max_turns: 5 ) client = ClaudeAgentSDK::Client.new(options: options) begin client.connect client.query(message_content) client.receive_response do |message| case message when ClaudeAgentSDK::AssistantMessage text = message.content .select { |b| b.is_a?(ClaudeAgentSDK::TextBlock) } .map(&:text) .join("\n") ChatChannel.broadcast_to(chat_id, { type: 'chunk', content: text }) when ClaudeAgentSDK::ResultMessage ChatChannel.broadcast_to(chat_id, { type: 'complete', cost: message.total_cost_usd, session_id: message.session_id }) end end ensure client.disconnect end end.wait end end ``` -------------------------------- ### Load System Prompt from File Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/plugins/claude-agent-ruby/skills/claude-agent-ruby/references/options.md Load the system prompt content from a specified file path. ```ruby ClaudeAgentSDK::SystemPromptFile.new(path: '/path/to/prompt.txt') ``` -------------------------------- ### Configure Sandbox Settings Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/README.md Sets up sandbox runtime restrictions and permission modes. ```ruby sandbox = ClaudeAgentSDK::SandboxSettings.new( enabled: true, auto_allow_bash_if_sandboxed: true, network: ClaudeAgentSDK::SandboxNetworkConfig.new( allow_local_binding: true ) ) options = ClaudeAgentSDK::ClaudeAgentOptions.new( sandbox: sandbox, permission_mode: 'acceptEdits' ) ClaudeAgentSDK.query(prompt: "Run some commands", options: options) do |message| puts message end ``` -------------------------------- ### Background Jobs with Error Handling in Rails Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/README.md Implement background jobs for Claude agent tasks with robust error handling. This example uses `retry_on` for specific SDK errors and rescues `CLINotFoundError` to update task status. ```ruby class ClaudeAgentJob < ApplicationJob queue_as :claude_agents retry_on ClaudeAgentSDK::ProcessError, wait: :polynomially_longer, attempts: 3 def perform(task_id) task = Task.find(task_id) Async do execute_agent(task) end.wait rescue ClaudeAgentSDK::CLINotFoundError => e task.update!(status: 'failed', error: 'Claude CLI not installed') raise end private def execute_agent(task) # ... agent execution end end ``` -------------------------------- ### Create Resources and Prompts Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/README.md Defines data resources and reusable prompt templates for the agent. ```ruby # Create a resource (data source Claude can read) config_resource = ClaudeAgentSDK.create_resource( uri: 'config://app/settings', name: 'Application Settings', description: 'Current app configuration', mime_type: 'application/json' ) do config_data = { app_name: 'MyApp', version: '1.0.0' } { contents: [{ uri: 'config://app/settings', mimeType: 'application/json', text: JSON.pretty_generate(config_data) }] } end # Create a prompt template review_prompt = ClaudeAgentSDK.create_prompt( name: 'code_review', description: 'Review code for best practices', arguments: [ { name: 'code', description: 'Code to review', required: true } ] ) do |args| { messages: [{ role: 'user', content: { type: 'text', text: "Review this code: #{args[:code]}" } }] } end # Create server with tools, resources, and prompts server = ClaudeAgentSDK.create_sdk_mcp_server( name: 'dev-tools', tools: [my_tool], resources: [config_resource], prompts: [review_prompt] ) ``` -------------------------------- ### Define Calculator Tools and Server Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/README.md Creates multiple tools and registers them within an MCP server instance. ```ruby # Define calculator tools add_tool = ClaudeAgentSDK.create_tool('add', 'Add two numbers', { a: :number, b: :number }) do |args| result = args[:a] + args[:b] { content: [{ type: 'text', text: "#{args[:a]} + #{args[:b]} = #{result}" }] } end divide_tool = ClaudeAgentSDK.create_tool('divide', 'Divide numbers', { a: :number, b: :number }) do |args| if args[:b] == 0 { content: [{ type: 'text', text: 'Error: Division by zero' }], is_error: true } else result = args[:a] / args[:b] { content: [{ type: 'text', text: "Result: #{result}" }] } end end # Create server calculator = ClaudeAgentSDK.create_sdk_mcp_server( name: 'calculator', tools: [add_tool, divide_tool] ) options = ClaudeAgentSDK::ClaudeAgentOptions.new( mcp_servers: { calc: calculator }, allowed_tools: ['mcp__calc__add', 'mcp__calc__divide'] ) ``` -------------------------------- ### Create SDK MCP tools Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/skills/references/usage-map.md Define tools for the agent using various parameter configurations and schema definitions. ```ruby tool = ClaudeAgentSDK.create_tool( 'greet', 'Greet a user', { name: :string }, annotations: { title: 'Greeter', readOnlyHint: true } ) do |args| { content: [{ type: 'text', text: "Hello, #{args[:name]}!" }] } end server = ClaudeAgentSDK.create_sdk_mcp_server(name: 'tools', tools: [tool]) options = ClaudeAgentSDK::ClaudeAgentOptions.new( mcp_servers: { tools: server }, allowed_tools: ['mcp__tools__greet'] ) ``` ```ruby tool = ClaudeAgentSDK.create_tool('save', 'Save a fact', { 'type' => 'object', 'properties' => { 'fact' => { 'type' => 'string' } }, 'required' => ['fact'] }) { |args| { content: [{ type: 'text', text: "Saved: #{args[:fact]}" }] } } ``` ```ruby tool = ClaudeAgentSDK.create_tool('ping', 'Ping the server', {}) do |_args| { content: [{ type: 'text', text: 'pong' }] } end ``` -------------------------------- ### Claude Agent Ruby SDK - Implementation Checklist Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/skills/SKILL.md Details the implementation checklist for using the Claude Agent Ruby SDK, including prerequisites and message handling. ```APIDOC ## Implementation Checklist - Confirm prerequisites (Ruby 3.2+, Node.js, Claude Code CLI). - Build `ClaudeAgentSDK::ClaudeAgentOptions` and pass it to `query` or `Client.new`. - Handle messages by type — the SDK has **24 typed message classes**: - Core: `AssistantMessage`, `UserMessage`, `ResultMessage`, `StreamEvent`, `RateLimitEvent` - System init: `InitMessage` (session start / /clear — carries uuid, session_id, tools, model, cwd, agents, betas, claude_code_version, permission_mode, slash_commands, output_style, skills, plugins, fast_mode_state) - Compaction: `CompactBoundaryMessage` (uuid, session_id, compact_metadata with pre_tokens, trigger, preserved_segment) - Status: `StatusMessage` (compacting status, permission mode changes) - Tasks: `TaskStartedMessage` (+ workflow_name, prompt), `TaskProgressMessage` (+ summary), `TaskNotificationMessage` - Hooks: `HookStartedMessage`, `HookProgressMessage`, `HookResponseMessage` - Sessions: `SessionStateChangedMessage` (idle/running/requires_action) - Tools: `ToolProgressMessage` (elapsed_time_seconds per tool), `ToolUseSummaryMessage` - Auth: `AuthStatusMessage` (isAuthenticating, output, error) - Files: `FilesPersistedMessage` (files, failed, processed_at) - API: `APIRetryMessage` (attempt, max_retries, retry_delay_ms, error_status) - Other: `LocalCommandOutputMessage`, `ElicitationCompleteMessage`, `PromptSuggestionMessage` - Unknown message types return `nil` (forward-compatible) - Handle content blocks: `TextBlock`, `ThinkingBlock`, `ToolUseBlock`, `ToolResultBlock`, `UnknownBlock` - `AssistantMessage` carries: `content`, `model`, `parent_tool_use_id`, `error`, `usage`, `message_id` (API message ID), `stop_reason`, `session_id`, `uuid` (transcript UUID) - `ResultMessage` carries: `stop_reason`, `model_usage` (per-model breakdown), `permission_denials`, `errors` (on error subtypes), `uuid`, `fast_mode_state` - Use `output_format` for JSON schema structured output - Use `thinking:` with `ThinkingConfigAdaptive`, `ThinkingConfigEnabled(budget_tokens:)`, or `ThinkingConfigDisabled`. Use `effort:` for effort level. ``` -------------------------------- ### Enable Beta Features Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/README.md Enables experimental features via the betas option. ```ruby options = ClaudeAgentSDK::ClaudeAgentOptions.new( betas: ['context-1m-2025-08-07'] # Extended context window ) ClaudeAgentSDK.query(prompt: "Analyze this large document...", options: options) do |message| puts message end ``` -------------------------------- ### Configure OTel for Langfuse Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/README.md Set up the OpenTelemetry SDK to export traces to a Langfuse instance using Basic Auth. ```ruby require 'base64' require 'opentelemetry/sdk' require 'opentelemetry/exporter/otlp' # Langfuse authenticates via Basic Auth over OTLP public_key = ENV['LANGFUSE_PUBLIC_KEY'] secret_key = ENV['LANGFUSE_SECRET_KEY'] auth = Base64.strict_encode64("#{public_key}:#{secret_key}") # Self-hosted or cloud: https://cloud.langfuse.com (EU) / https://us.cloud.langfuse.com (US) langfuse_host = ENV.fetch('LANGFUSE_HOST', 'https://cloud.langfuse.com') OpenTelemetry::SDK.configure do |c| c.service_name = 'my-agent-app' c.add_span_processor( OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new( OpenTelemetry::Exporter::OTLP::Exporter.new( endpoint: "#{langfuse_host}/api/public/otel/v1/traces", headers: { 'Authorization' => "Basic #{auth}", 'x-langfuse-ingestion-version' => '4' } ) ) ) end ``` -------------------------------- ### Instantiate Client with Custom Transport Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/plugins/claude-agent-ruby/skills/claude-agent-ruby/references/options.md Create a client instance using a custom transport class and arguments. The custom transport must implement the `Transport` interface. ```ruby client = ClaudeAgentSDK::Client.new( options: options, transport_class: MyCustomTransport, transport_args: { host: "localhost", port: 9000 } ) ``` -------------------------------- ### Use streaming input helpers Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/plugins/claude-agent-ruby/skills/claude-agent-ruby/references/message-handling.md Demonstrates creating streams from arrays or blocks, and generating user message JSON. ```ruby # From an array of strings stream = ClaudeAgentSDK::Streaming.from_array(["Hello", "What is 2+2?", "Thanks!"]) ClaudeAgentSDK.query(prompt: stream) { |msg| puts msg.inspect } # From a block (useful for delayed/interactive input) stream = ClaudeAgentSDK::Streaming.from_block do |yielder| yielder << "First message" sleep 1 yielder << "Second message" end # Build a single user message (returns JSON string) json = ClaudeAgentSDK::Streaming.user_message("Hello", session_id: "default") ``` -------------------------------- ### SDK MCP Tool Creation with Annotations Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/plugins/claude-agent-ruby/skills/claude-agent-ruby/references/usage-map.md Defines a custom tool for SDK MCP servers with optional annotations for metadata. The tool takes a 'name' argument and returns a greeting. ```ruby tool = ClaudeAgentSDK.create_tool( 'greet', 'Greet a user', { name: :string }, annotations: { title: 'Greeter', readOnlyHint: true } ) do |args| { content: [{ type: 'text', text: "Hello, #{args[:name]}!" }] } end server = ClaudeAgentSDK.create_sdk_mcp_server(name: 'tools', tools: [tool]) options = ClaudeAgentSDK::ClaudeAgentOptions.new( mcp_servers: { tools: server }, allowed_tools: ['mcp__tools__greet'] ) ``` -------------------------------- ### Tool Definition with Symbol Keys in Ruby Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/README.md Shows how to define a tool using `ClaudeAgentSDK.create_tool` with symbol keys for arguments, which is the standard Ruby convention. The SDK transparently handles both symbol-keyed and string-keyed schemas. ```ruby # Symbol keys (standard Ruby) tool = ClaudeAgentSDK.create_tool('save', 'Save a fact', { type: 'object', properties: { fact: { type: 'string' } }, required: ['fact'] }) { |args| { content: [{ type: 'text', text: "Saved: #{args[:fact]}" }] } } ``` -------------------------------- ### Connect and Query with Claude Client Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/README.md Use an Async block to manage the client lifecycle, including connection, querying, and message reception. ```ruby Async do client = ClaudeAgentSDK::Client.new(options: options) client.connect client.query("Hello") client.receive_messages { |msg| puts msg } client.disconnect end.wait ``` -------------------------------- ### Run integration tests Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/spec/README.md Commands to execute integration tests, which are skipped by default. ```bash RUN_INTEGRATION=1 bundle exec rspec ``` ```bash RUN_INTEGRATION=1 RUN_REAL_INTEGRATION=1 ANTHROPIC_API_KEY=... bundle exec rspec spec/integration/real_cli_integration_spec.rb ``` -------------------------------- ### Query with Tool Permissions (Ruby) Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/README.md Configure query options to allow specific tools and set the permission mode for automatic acceptance of file edits. ```ruby options = ClaudeAgentSDK::ClaudeAgentOptions.new( allowed_tools: ['Read', 'Write', 'Bash'], permission_mode: 'acceptEdits' # auto-accept file edits ) ClaudeAgentSDK.query( prompt: "Create a hello.rb file", options: options ) do |message| # Process tool use and results end ``` -------------------------------- ### Configure Claude Agent SDK with Instrumentation Source: https://github.com/ya-luotao/claude-agent-sdk-ruby/blob/main/README.md Configure the SDK to automatically trace queries and client sessions using OpenTelemetry observers. Use a lambda factory for thread-safe observer instances. ```ruby require 'claude_agent_sdk/instrumentation' ClaudeAgentSDK.configure do |config| config.default_options = { permission_mode: 'bypassPermissions', observers: ENV['LANGFUSE_PUBLIC_KEY'].present? ? [ # Use a lambda so each query gets a fresh observer instance (thread-safe). # A single shared instance would have its span state clobbered by concurrent requests. -> { ClaudeAgentSDK::Instrumentation::OTelObserver.new } ] : [] } end ``` -------------------------------- ### Implement Budget Control Source: https://context7.com/ya-luotao/claude-agent-sdk-ruby/llms.txt Set spending caps and monitor usage metrics for API requests. ```ruby require 'claude_agent_sdk' options = ClaudeAgentSDK::ClaudeAgentOptions.new( max_budget_usd: 0.50, # Cap at $0.50 max_turns: 10, model: 'claude-sonnet-4-20250514', fallback_model: 'claude-3-5-haiku-20241022' ) ClaudeAgentSDK.query(prompt: "Analyze this large codebase", options: options) do |message| if message.is_a?(ClaudeAgentSDK::ResultMessage) puts "Total cost: $#{message.total_cost_usd}" puts "Duration: #{message.duration_ms}ms" puts "API duration: #{message.duration_api_ms}ms" puts "Turns used: #{message.num_turns}" puts "Stop reason: #{message.stop_reason}" if message.usage puts "Input tokens: #{message.usage[:input_tokens]}" puts "Output tokens: #{message.usage[:output_tokens]}" end end end ``` -------------------------------- ### Create Custom Tools with SDK MCP Servers Source: https://context7.com/ya-luotao/claude-agent-sdk-ruby/llms.txt Define custom tools directly within your Ruby application using `create_tool`. These tools run in-process and can handle arguments and return content or errors. ```ruby require 'claude_agent_sdk' require 'async' # Define a greeting tool with annotations greet_tool = ClaudeAgentSDK.create_tool( 'greet', 'Greet a user by name', { name: :string }, annotations: { title: 'Greeter', readOnlyHint: true } ) do |args| { content: [{ type: 'text', text: "Hello, #{args[:name]}! Welcome!" }] } end # Define a calculator tool with error handling divide_tool = ClaudeAgentSDK.create_tool( 'divide', 'Divide two numbers', { a: :number, b: :number } ) do |args| if args[:b] == 0 { content: [{ type: 'text', text: 'Error: Division by zero' }], is_error: true } else result = args[:a].to_f / args[:b] { content: [{ type: 'text', text: "#{args[:a]} / #{args[:b]} = #{result}" }] } end end ```