Module: ClaudeAgentSDK
- Defined in:
- lib/claude_agent_sdk.rb,
lib/claude_agent_sdk/query.rb,
lib/claude_agent_sdk/types.rb,
lib/claude_agent_sdk/errors.rb,
lib/claude_agent_sdk/version.rb,
lib/claude_agent_sdk/observer.rb,
lib/claude_agent_sdk/sessions.rb,
lib/claude_agent_sdk/streaming.rb,
lib/claude_agent_sdk/transport.rb,
lib/claude_agent_sdk/configuration.rb,
lib/claude_agent_sdk/session_store.rb,
lib/claude_agent_sdk/fiber_boundary.rb,
lib/claude_agent_sdk/message_parser.rb,
lib/claude_agent_sdk/sdk_mcp_server.rb,
lib/claude_agent_sdk/session_resume.rb,
lib/claude_agent_sdk/command_builder.rb,
lib/claude_agent_sdk/session_summary.rb,
lib/claude_agent_sdk/session_mutations.rb,
lib/claude_agent_sdk/instrumentation/otel.rb,
lib/claude_agent_sdk/subprocess_cli_transport.rb,
lib/claude_agent_sdk/transcript_mirror_batcher.rb,
lib/claude_agent_sdk/testing/session_store_conformance.rb
Overview
Claude Agent SDK for Ruby
Defined Under Namespace
Modules: FiberBoundary, Instrumentation, Observer, SessionMutations, SessionResume, SessionStores, SessionSummary, Sessions, Streaming, Testing Classes: APIRetryMessage, AgentDefinition, AssistantMessage, AsyncHookJSONOutput, AuthStatusMessage, BaseHookInput, CLIConnectionError, CLIJSONDecodeError, CLINotFoundError, ClaudeAgentOptions, ClaudeSDKError, Client, CommandBuilder, CompactBoundaryMessage, CompactMetadata, ConfigChangeHookInput, Configuration, ControlRequestTimeoutError, CwdChangedHookInput, CwdChangedHookSpecificOutput, DeferredToolUse, ElicitationCompleteMessage, ElicitationHookInput, ElicitationResultHookInput, FileChangedHookInput, FileChangedHookSpecificOutput, FilesPersistedMessage, ForkSessionResult, HookContext, HookMatcher, HookProgressMessage, HookResponseMessage, HookStartedMessage, InMemorySessionStore, InitMessage, InstructionsLoadedHookInput, LocalCommandOutputMessage, MaterializedResume, McpClaudeAIProxyServerConfig, McpHttpServerConfig, McpSSEServerConfig, McpSdkServerConfig, McpSdkServerConfigStatus, McpServerInfo, McpServerStatus, McpStatusResponse, McpStdioServerConfig, McpToolAnnotations, McpToolInfo, MessageParseError, MessageParser, MirrorErrorMessage, NotificationHookInput, NotificationHookSpecificOutput, PermissionDeniedHookInput, PermissionDeniedHookSpecificOutput, PermissionRequestHookInput, PermissionRequestHookSpecificOutput, PermissionResultAllow, PermissionResultDeny, PermissionRuleValue, PermissionUpdate, PostCompactHookInput, PostToolUseFailureHookInput, PostToolUseFailureHookSpecificOutput, PostToolUseHookInput, PostToolUseHookSpecificOutput, PreCompactHookInput, PreToolUseHookInput, PreToolUseHookSpecificOutput, ProcessError, PromptSuggestionMessage, Query, RateLimitEvent, RateLimitInfo, ResultMessage, SDKSessionInfo, SandboxFilesystemConfig, SandboxNetworkConfig, SandboxSettings, SdkMcpPrompt, SdkMcpResource, SdkMcpServer, SdkMcpTool, SdkPluginConfig, ServerToolResultBlock, ServerToolUseBlock, SessionEndHookInput, SessionMessage, SessionStartHookInput, SessionStartHookSpecificOutput, SessionStateChangedMessage, SessionStore, SetupHookInput, SetupHookSpecificOutput, StatusMessage, StopFailureHookInput, StopHookInput, StreamEvent, SubagentStartHookInput, SubagentStartHookSpecificOutput, SubagentStopHookInput, SubprocessCLITransport, SyncHookJSONOutput, SystemMessage, SystemPromptFile, SystemPromptPreset, TaskBudget, TaskCompletedHookInput, TaskCreatedHookInput, TaskNotificationMessage, TaskProgressMessage, TaskStartedMessage, TaskUsage, TeammateIdleHookInput, TextBlock, ThinkingBlock, ThinkingConfigAdaptive, ThinkingConfigDisabled, ThinkingConfigEnabled, ToolPermissionContext, ToolProgressMessage, ToolResultBlock, ToolUseBlock, ToolUseSummaryMessage, ToolsPreset, TranscriptMirrorBatcher, Transport, Type, UnknownBlock, UserMessage, UserPromptSubmitHookInput, UserPromptSubmitHookSpecificOutput, WorktreeCreateHookInput, WorktreeRemoveHookInput
Constant Summary collapse
- PERMISSION_MODES =
Type constants for permission modes
%w[default acceptEdits plan bypassPermissions dontAsk auto].freeze
- SETTING_SOURCES =
Type constants for setting sources
%w[user project local].freeze
- EFFORT_LEVELS =
Effort levels for ‘ClaudeAgentOptions#effort`. The CLI (Claude Code 2.1.111+) accepts these values; the set of supported levels is model-dependent (e.g. `xhigh` is only supported on Opus 4.7 and falls back to `high` on Opus 4.6 / Sonnet 4.6). An Integer is also accepted and forwarded verbatim.
%w[low medium high xhigh max].freeze
- PERMISSION_UPDATE_DESTINATIONS =
Type constants for permission update destinations
%w[userSettings projectSettings localSettings session].freeze
- PERMISSION_BEHAVIORS =
Type constants for permission behaviors
%w[allow deny ask].freeze
- HOOK_EVENTS =
Type constants for hook events
%w[ PreToolUse PostToolUse PostToolUseFailure Notification UserPromptSubmit SessionStart SessionEnd Stop StopFailure SubagentStart SubagentStop PreCompact PostCompact PermissionRequest PermissionDenied Setup TeammateIdle TaskCreated TaskCompleted Elicitation ElicitationResult ConfigChange WorktreeCreate WorktreeRemove InstructionsLoaded CwdChanged FileChanged ].freeze
- ASSISTANT_MESSAGE_ERRORS =
Type constants for assistant message errors
%w[authentication_failed billing_error rate_limit invalid_request server_error max_output_tokens unknown].freeze
- SDK_BETAS =
Type constants for SDK beta features Available beta features that can be enabled via the betas option
%w[context-1m-2025-08-07].freeze
- TASK_NOTIFICATION_STATUSES =
Task lifecycle notification statuses
%w[completed failed stopped].freeze
- RATE_LIMIT_STATUSES =
Type constants for rate limit statuses
%w[allowed allowed_warning rejected].freeze
- RATE_LIMIT_TYPES =
Type constants for rate limit types
%w[five_hour seven_day seven_day_opus seven_day_sonnet overage].freeze
- THINKING_DISPLAY_VALUES =
Thinking configuration types
‘display` controls how thinking content appears in responses. Valid values are `“summarized”` (plaintext summary) and `“omitted”` (empty thinking field, signature only). Defaults are model-dependent: Opus 4.6/Sonnet 4.6 default to `“summarized”`; Opus 4.7 and Mythos Preview default to `“omitted”`. Pass `display: “summarized”` explicitly on Opus 4.7 to get visible thinking text. Not supported with `ThinkingConfigDisabled`.
%w[summarized omitted].freeze
- MCP_SERVER_CONNECTION_STATUSES =
MCP server connection status values
%w[connected failed needs-auth pending disabled].freeze
- VERSION =
'0.17.0'- SESSION_STORE_FLUSH_MODES =
Controls when transcript-mirror entries are flushed to a SessionStore.
-
“batched” (default): buffer entries and flush once per turn (on the ‘result` message) or when the pending buffer exceeds 500 entries / 1 MiB.
-
“eager”: trigger a background flush after every transcript_mirror frame so SessionStore#append sees entries in near real time.
-
%w[batched eager].freeze
Class Method Summary collapse
-
.configuration ⇒ Configuration
Get the configuration object.
-
.configure {|Configuration| ... } ⇒ Object
Configure the SDK with default options.
-
.create_prompt(name:, description: nil, arguments: nil, &generator) ⇒ SdkMcpPrompt
Helper function to create a prompt definition.
-
.create_resource(uri:, name:, description: nil, mime_type: nil, &reader) ⇒ SdkMcpResource
Helper function to create a resource definition.
-
.create_sdk_mcp_server(name:, version: '1.0.0', tools: [], resources: [], prompts: []) ⇒ Hash
Create an SDK MCP server.
-
.create_tool(name, description, input_schema, annotations: nil, meta: nil, &handler) ⇒ SdkMcpTool
Helper function to create a tool definition.
-
.deep_symbolize_keys(obj) ⇒ Object
Recursively convert all hash keys to symbols.
-
.default_options ⇒ Hash
Get merged default options for use with ClaudeAgentOptions.
-
.delete_session(session_id:, directory: nil) ⇒ Object
Delete a session by removing its JSONL file (hard delete).
-
.delete_session_via_store(session_store:, session_id:, directory: nil) ⇒ Object
Delete a session from a SessionStore (store-backed counterpart to delete_session).
-
.flexible_fetch(hash, camel_key, snake_key) ⇒ Object
Look up a value in a hash that may use symbol or string keys in camelCase or snake_case.
-
.fold_session_summary(prev, key, entries) ⇒ Hash
Fold a batch of appended transcript entries into a running session summary.
-
.fork_session(session_id:, directory: nil, up_to_message_id: nil, title: nil) ⇒ ForkSessionResult
Fork a session into a new branch with fresh UUIDs.
-
.fork_session_via_store(session_store:, session_id:, directory: nil, up_to_message_id: nil, title: nil) ⇒ ForkSessionResult
Fork a session in a SessionStore into a new branch with fresh UUIDs (store-backed counterpart to fork_session).
-
.get_session_info(session_id:, directory: nil) ⇒ SDKSessionInfo?
Read metadata for a single session by ID (no full directory scan).
-
.get_session_info_from_store(session_store:, session_id:, directory: nil) ⇒ SDKSessionInfo?
Read metadata for a single session from a SessionStore.
-
.get_session_messages(session_id:, directory: nil, limit: nil, offset: 0) ⇒ Array<SessionMessage>
Get messages from a session transcript.
-
.get_session_messages_from_store(session_store:, session_id:, directory: nil, limit: nil, offset: 0) ⇒ Array<SessionMessage>
Read a session’s conversation messages from a SessionStore.
-
.get_subagent_messages_from_store(session_store:, session_id:, agent_id:, directory: nil, limit: nil, offset: 0) ⇒ Array<SessionMessage>
Read a subagent’s conversation messages from a SessionStore.
-
.import_session_to_store(session_id:, session_store:, directory: nil, include_subagents: true, batch_size: TranscriptMirrorBatcher::MAX_PENDING_ENTRIES) ⇒ Object
Replay a local on-disk session transcript into a SessionStore (migration / gap-backfill).
-
.list_sessions(directory: nil, limit: nil, offset: 0, include_worktrees: true) {|Message| ... } ⇒ Enumerator, Array<SDKSessionInfo>
Query Claude Code for one-shot or unidirectional streaming interactions.
-
.list_sessions_from_store(session_store:, directory: nil, limit: nil, offset: 0) ⇒ Array<SDKSessionInfo>
List sessions from a SessionStore (store-backed counterpart to list_sessions).
-
.list_subagents_from_store(session_store:, session_id:, directory: nil) ⇒ Array<String>
List subagent IDs for a session from a SessionStore (requires list_subkeys).
-
.notify_observers(observers, method, *args) ⇒ Object
Safely call a method on each observer, suppressing any errors.
-
.project_key_for_directory(directory = nil) ⇒ String
Derive the SessionStore
project_keyfor a directory (default: cwd). - .query(prompt:, options: nil, &block) ⇒ Object
-
.rename_session(session_id:, title:, directory: nil) ⇒ Object
Rename a session by appending a custom-title entry.
-
.rename_session_via_store(session_store:, session_id:, title:, directory: nil) ⇒ Object
Rename a session in a SessionStore (store-backed counterpart to rename_session).
-
.reset_configuration ⇒ Object
Reset configuration to defaults (useful for testing).
-
.resolve_observers(observers) ⇒ Object
Resolve observers array: callables (Proc/lambda) are invoked to produce a fresh instance per query/session (thread-safe); plain objects are used as-is.
-
.tag_session(session_id:, tag:, directory: nil) ⇒ Object
Tag a session.
-
.tag_session_via_store(session_store:, session_id:, tag:, directory: nil) ⇒ Object
Tag a session in a SessionStore (store-backed counterpart to tag_session).
Class Method Details
.configuration ⇒ Configuration
Get the configuration object
58 59 60 |
# File 'lib/claude_agent_sdk/configuration.rb', line 58 def configuration @configuration ||= Configuration.new end |
.configure {|Configuration| ... } ⇒ Object
Configure the SDK with default options
51 52 53 |
# File 'lib/claude_agent_sdk/configuration.rb', line 51 def configure yield(configuration) end |
.create_prompt(name:, description: nil, arguments: nil, &generator) ⇒ SdkMcpPrompt
Helper function to create a prompt definition
531 532 533 534 535 536 537 538 539 540 |
# File 'lib/claude_agent_sdk/sdk_mcp_server.rb', line 531 def self.create_prompt(name:, description: nil, arguments: nil, &generator) raise ArgumentError, 'Block required for prompt generator' unless generator SdkMcpPrompt.new( name: name, description: description, arguments: arguments, generator: generator ) end |
.create_resource(uri:, name:, description: nil, mime_type: nil, &reader) ⇒ SdkMcpResource
Helper function to create a resource definition
473 474 475 476 477 478 479 480 481 482 483 |
# File 'lib/claude_agent_sdk/sdk_mcp_server.rb', line 473 def self.create_resource(uri:, name:, description: nil, mime_type: nil, &reader) raise ArgumentError, 'Block required for resource reader' unless reader SdkMcpResource.new( uri: uri, name: name, description: description, mime_type: mime_type, reader: reader ) end |
.create_sdk_mcp_server(name:, version: '1.0.0', tools: [], resources: [], prompts: []) ⇒ Hash
Create an SDK MCP server
583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 |
# File 'lib/claude_agent_sdk/sdk_mcp_server.rb', line 583 def self.create_sdk_mcp_server(name:, version: '1.0.0', tools: [], resources: [], prompts: []) server = SdkMcpServer.new( name: name, version: version, tools: tools, resources: resources, prompts: prompts ) # Return configuration for ClaudeAgentOptions { type: 'sdk', name: name, instance: server } end |
.create_tool(name, description, input_schema, annotations: nil, meta: nil, &handler) ⇒ SdkMcpTool
Helper function to create a tool definition
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 |
# File 'lib/claude_agent_sdk/sdk_mcp_server.rb', line 412 def self.create_tool(name, description, input_schema, annotations: nil, meta: nil, &handler) raise ArgumentError, 'Block required for tool handler' unless handler # Auto-populate _meta with maxResultSizeChars from annotations if present = if .nil? && annotations max_chars = annotations[:maxResultSizeChars] || annotations['maxResultSizeChars'] = { 'anthropic/maxResultSizeChars' => max_chars } if max_chars end SdkMcpTool.new( name: name, description: description, input_schema: input_schema, handler: handler, annotations: annotations, meta: ) end |
.deep_symbolize_keys(obj) ⇒ Object
Recursively convert all hash keys to symbols
7 8 9 10 11 12 13 |
# File 'lib/claude_agent_sdk/sdk_mcp_server.rb', line 7 def self.deep_symbolize_keys(obj) case obj when Hash then obj.transform_keys(&:to_sym).transform_values { |v| deep_symbolize_keys(v) } when Array then obj.map { |v| deep_symbolize_keys(v) } else obj end end |
.default_options ⇒ Hash
Get merged default options for use with ClaudeAgentOptions
70 71 72 |
# File 'lib/claude_agent_sdk/configuration.rb', line 70 def configuration. || {} end |
.delete_session(session_id:, directory: nil) ⇒ Object
Delete a session by removing its JSONL file (hard delete).
133 134 135 |
# File 'lib/claude_agent_sdk.rb', line 133 def self.delete_session(session_id:, directory: nil) SessionMutations.delete_session(session_id: session_id, directory: directory) end |
.delete_session_via_store(session_store:, session_id:, directory: nil) ⇒ Object
Delete a session from a SessionStore (store-backed counterpart to delete_session). No-op when the store does not implement #delete (WORM/append-only backends).
223 224 225 226 |
# File 'lib/claude_agent_sdk.rb', line 223 def self.delete_session_via_store(session_store:, session_id:, directory: nil) SessionMutations.delete_session_via_store(session_store: session_store, session_id: session_id, directory: directory) end |
.flexible_fetch(hash, camel_key, snake_key) ⇒ Object
Look up a value in a hash that may use symbol or string keys in camelCase or snake_case. Returns the first non-nil value found, preserving false as a meaningful value.
49 50 51 52 53 54 55 |
# File 'lib/claude_agent_sdk.rb', line 49 def self.flexible_fetch(hash, camel_key, snake_key) val = hash[camel_key.to_sym] val = hash[camel_key.to_s] if val.nil? val = hash[snake_key.to_sym] if val.nil? val = hash[snake_key.to_s] if val.nil? val end |
.fold_session_summary(prev, key, entries) ⇒ Hash
Fold a batch of appended transcript entries into a running session summary. SessionStore adapters call this inside #append to maintain a summary sidecar incrementally (see SessionStore#list_session_summaries).
164 165 166 |
# File 'lib/claude_agent_sdk.rb', line 164 def self.fold_session_summary(prev, key, entries) SessionSummary.fold_session_summary(prev, key, entries) end |
.fork_session(session_id:, directory: nil, up_to_message_id: nil, title: nil) ⇒ ForkSessionResult
Fork a session into a new branch with fresh UUIDs.
143 144 145 146 |
# File 'lib/claude_agent_sdk.rb', line 143 def self.fork_session(session_id:, directory: nil, up_to_message_id: nil, title: nil) SessionMutations.fork_session(session_id: session_id, directory: directory, up_to_message_id: , title: title) end |
.fork_session_via_store(session_store:, session_id:, directory: nil, up_to_message_id: nil, title: nil) ⇒ ForkSessionResult
Fork a session in a SessionStore into a new branch with fresh UUIDs (store-backed counterpart to fork_session).
233 234 235 236 |
# File 'lib/claude_agent_sdk.rb', line 233 def self.fork_session_via_store(session_store:, session_id:, directory: nil, up_to_message_id: nil, title: nil) SessionMutations.fork_session_via_store(session_store: session_store, session_id: session_id, directory: directory, up_to_message_id: , title: title) end |
.get_session_info(session_id:, directory: nil) ⇒ SDKSessionInfo?
Read metadata for a single session by ID (no full directory scan)
100 101 102 |
# File 'lib/claude_agent_sdk.rb', line 100 def self.get_session_info(session_id:, directory: nil) Sessions.get_session_info(session_id: session_id, directory: directory) end |
.get_session_info_from_store(session_store:, session_id:, directory: nil) ⇒ SDKSessionInfo?
Read metadata for a single session from a SessionStore.
177 178 179 |
# File 'lib/claude_agent_sdk.rb', line 177 def self.get_session_info_from_store(session_store:, session_id:, directory: nil) Sessions.get_session_info_from_store(session_store: session_store, session_id: session_id, directory: directory) end |
.get_session_messages(session_id:, directory: nil, limit: nil, offset: 0) ⇒ Array<SessionMessage>
Get messages from a session transcript
110 111 112 |
# File 'lib/claude_agent_sdk.rb', line 110 def self.(session_id:, directory: nil, limit: nil, offset: 0) Sessions.(session_id: session_id, directory: directory, limit: limit, offset: offset) end |
.get_session_messages_from_store(session_store:, session_id:, directory: nil, limit: nil, offset: 0) ⇒ Array<SessionMessage>
Read a session’s conversation messages from a SessionStore.
183 184 185 186 |
# File 'lib/claude_agent_sdk.rb', line 183 def self.(session_store:, session_id:, directory: nil, limit: nil, offset: 0) Sessions.(session_store: session_store, session_id: session_id, directory: directory, limit: limit, offset: offset) end |
.get_subagent_messages_from_store(session_store:, session_id:, agent_id:, directory: nil, limit: nil, offset: 0) ⇒ Array<SessionMessage>
Read a subagent’s conversation messages from a SessionStore.
196 197 198 199 200 |
# File 'lib/claude_agent_sdk.rb', line 196 def self.(session_store:, session_id:, agent_id:, directory: nil, limit: nil, offset: 0) Sessions.(session_store: session_store, session_id: session_id, agent_id: agent_id, directory: directory, limit: limit, offset: offset) end |
.import_session_to_store(session_id:, session_store:, directory: nil, include_subagents: true, batch_size: TranscriptMirrorBatcher::MAX_PENDING_ENTRIES) ⇒ Object
Replay a local on-disk session transcript into a SessionStore (migration / gap-backfill). Keys under the on-disk project dir so the imported session is resumable via session_store + resume from the original cwd.
243 244 245 246 247 |
# File 'lib/claude_agent_sdk.rb', line 243 def self.import_session_to_store(session_id:, session_store:, directory: nil, include_subagents: true, batch_size: TranscriptMirrorBatcher::MAX_PENDING_ENTRIES) Sessions.import_session_to_store(session_id: session_id, session_store: session_store, directory: directory, include_subagents: include_subagents, batch_size: batch_size) end |
.list_sessions(directory: nil, limit: nil, offset: 0, include_worktrees: true) {|Message| ... } ⇒ Enumerator, Array<SDKSessionInfo>
Query Claude Code for one-shot or unidirectional streaming interactions
This function is ideal for simple, stateless queries where you don’t need bidirectional communication or conversation management.
List sessions for a directory (or all sessions)
92 93 94 |
# File 'lib/claude_agent_sdk.rb', line 92 def self.list_sessions(directory: nil, limit: nil, offset: 0, include_worktrees: true) Sessions.list_sessions(directory: directory, limit: limit, offset: offset, include_worktrees: include_worktrees) end |
.list_sessions_from_store(session_store:, directory: nil, limit: nil, offset: 0) ⇒ Array<SDKSessionInfo>
List sessions from a SessionStore (store-backed counterpart to list_sessions).
171 172 173 |
# File 'lib/claude_agent_sdk.rb', line 171 def self.list_sessions_from_store(session_store:, directory: nil, limit: nil, offset: 0) Sessions.list_sessions_from_store(session_store: session_store, directory: directory, limit: limit, offset: offset) end |
.list_subagents_from_store(session_store:, session_id:, directory: nil) ⇒ Array<String>
List subagent IDs for a session from a SessionStore (requires list_subkeys).
190 191 192 |
# File 'lib/claude_agent_sdk.rb', line 190 def self.list_subagents_from_store(session_store:, session_id:, directory: nil) Sessions.list_subagents_from_store(session_store: session_store, session_id: session_id, directory: directory) end |
.notify_observers(observers, method, *args) ⇒ Object
Safely call a method on each observer, suppressing any errors. Each observer is invoked through FiberBoundary so that user code runs on a plain thread (no Fiber scheduler) even when called from inside the SDK’s Async reactor.
39 40 41 42 43 44 45 |
# File 'lib/claude_agent_sdk.rb', line 39 def self.notify_observers(observers, method, *args) observers.each do |obs| FiberBoundary.invoke { obs.send(method, *args) } rescue StandardError nil end end |
.project_key_for_directory(directory = nil) ⇒ String
Derive the SessionStore project_key for a directory (default: cwd). Matches the CLI’s project-directory naming so keys align between local-disk and store-mirrored transcripts.
153 154 155 |
# File 'lib/claude_agent_sdk.rb', line 153 def self.project_key_for_directory(directory = nil) Sessions.project_key_for_directory(directory) end |
.query(prompt:, options: nil, &block) ⇒ Object
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 |
# File 'lib/claude_agent_sdk.rb', line 249 def self.query(prompt:, options: nil, &block) return enum_for(:query, prompt: prompt, options: ) unless block ||= ClaudeAgentOptions.new = if .can_use_tool if prompt.is_a?(String) raise ArgumentError, 'can_use_tool callback requires streaming mode. Please provide prompt as an Enumerator instead of a String.' end raise ArgumentError, 'can_use_tool callback cannot be used with permission_prompt_tool_name' if . = .dup_with(permission_prompt_tool_name: 'stdio') end # Fail fast on invalid session_store combinations before spawning the CLI. SessionStores.() # Resolve callable observers into fresh instances (thread-safe for global defaults) resolved_observers = ClaudeAgentSDK.resolve_observers(.observers) Async do materialized = nil transport = nil query_handler = nil begin # Resume-from-store: when a session_store is set and resume/continue is # requested, load the session into a temp CLAUDE_CONFIG_DIR and repoint # options at it (env + --resume) BEFORE spawning. Returns options # unchanged when no materialization applies. query() always uses the # default subprocess transport, so no custom-transport gate is needed. materialized = SessionResume.materialize_resume_session() = SessionResume.(, materialized) if materialized # Always use streaming mode with control protocol (matches Python SDK). # This sends agents via initialize request instead of CLI args, # avoiding OS ARG_MAX limits. transport = SubprocessCLITransport.new() transport.connect # Extract SDK MCP servers sdk_mcp_servers = {} if .mcp_servers.is_a?(Hash) .mcp_servers.each do |name, config| sdk_mcp_servers[name] = config[:instance] if config.is_a?(Hash) && config[:type] == 'sdk' end end hooks = nil if .hooks hooks = {} .hooks.each do |event, matchers| next if matchers.nil? || matchers.empty? entries = [] matchers.each do |matcher| config = { matcher: matcher.matcher, hooks: matcher.hooks } config[:timeout] = matcher.timeout if matcher.timeout entries << config end hooks[event.to_s] = entries unless entries.empty? end hooks = nil if hooks.empty? end # Create Query handler for control protocol query_handler = Query.new( transport: transport, is_streaming_mode: true, can_use_tool: .can_use_tool, hooks: hooks, agents: .agents, sdk_mcp_servers: sdk_mcp_servers ) # Mirror transcripts to the session_store, if configured. Installed # before #start so the read loop captures transcript_mirror frames. if .session_store query_handler.set_transcript_mirror_batcher( SessionResume.build_mirror_batcher( store: .session_store, env: .env, on_error: ->(key, ) { query_handler.report_mirror_error(key, ) }, eager: .session_store_flush.to_s == 'eager' ) ) end # Start reading messages in background query_handler.start # Initialize the control protocol (sends agents) query_handler.initialize_protocol # Send prompt(s) as user messages, then close stdin if prompt.is_a?(String) ClaudeAgentSDK.notify_observers(resolved_observers, :on_user_prompt, prompt) = { type: 'user', message: { role: 'user', content: prompt }, parent_tool_use_id: nil, session_id: '' } transport.write(JSON.generate() + "\n") query_handler.wait_for_result_and_end_input elsif prompt.is_a?(Enumerator) || prompt.respond_to?(:each) Async do query_handler.stream_input(prompt) end end # Read and yield messages from the query handler (filters out control messages). # User block is invoked through FiberBoundary so ActiveRecord / PG calls # inside it don't see the async gem's Fiber scheduler. query_handler. do |data| = MessageParser.parse(data) if ClaudeAgentSDK.notify_observers(resolved_observers, :on_message, ) FiberBoundary.invoke { block.call() } end end ensure ClaudeAgentSDK.notify_observers(resolved_observers, :on_close) # query_handler.close stops the background read task and closes the # transport (flushing the mirror batcher first). Fall back to a bare # transport close when the handler was never built. begin if query_handler query_handler.close elsif transport transport.close end ensure # Remove the materialized resume temp dir (which holds a redacted # .credentials.json copy) AFTER the subprocess has exited, even when # close itself raises. materialized&.cleanup end end end.wait end |
.rename_session(session_id:, title:, directory: nil) ⇒ Object
Rename a session by appending a custom-title entry
118 119 120 |
# File 'lib/claude_agent_sdk.rb', line 118 def self.rename_session(session_id:, title:, directory: nil) SessionMutations.rename_session(session_id: session_id, title: title, directory: directory) end |
.rename_session_via_store(session_store:, session_id:, title:, directory: nil) ⇒ Object
Rename a session in a SessionStore (store-backed counterpart to rename_session). Appends a custom-title entry carrying a fresh uuid + timestamp via SessionStore#append.
206 207 208 209 |
# File 'lib/claude_agent_sdk.rb', line 206 def self.rename_session_via_store(session_store:, session_id:, title:, directory: nil) SessionMutations.rename_session_via_store(session_store: session_store, session_id: session_id, title: title, directory: directory) end |
.reset_configuration ⇒ Object
Reset configuration to defaults (useful for testing)
63 64 65 |
# File 'lib/claude_agent_sdk/configuration.rb', line 63 def reset_configuration @configuration = Configuration.new end |
.resolve_observers(observers) ⇒ Object
Resolve observers array: callables (Proc/lambda) are invoked to produce a fresh instance per query/session (thread-safe); plain objects are used as-is. Array() guards against nil (e.g., when observers: nil is passed explicitly).
29 30 31 32 33 |
# File 'lib/claude_agent_sdk.rb', line 29 def self.resolve_observers(observers) Array(observers).map do |obs| obs.respond_to?(:call) ? obs.call : obs end end |
.tag_session(session_id:, tag:, directory: nil) ⇒ Object
Tag a session. Pass nil to clear the tag.
126 127 128 |
# File 'lib/claude_agent_sdk.rb', line 126 def self.tag_session(session_id:, tag:, directory: nil) SessionMutations.tag_session(session_id: session_id, tag: tag, directory: directory) end |
.tag_session_via_store(session_store:, session_id:, tag:, directory: nil) ⇒ Object
Tag a session in a SessionStore (store-backed counterpart to tag_session). Pass nil to clear the tag.
214 215 216 217 |
# File 'lib/claude_agent_sdk.rb', line 214 def self.tag_session_via_store(session_store:, session_id:, tag:, directory: nil) SessionMutations.tag_session_via_store(session_store: session_store, session_id: session_id, tag: tag, directory: directory) end |