Class: Silas::Engines::AgentSdk
- Defined in:
- lib/silas/engines/agent_sdk.rb
Overview
The engine-owned adapter: one claude -p subprocess runs a whole agentic
turn, calling back into Silas tools over an in-worker HTTP MCP endpoint
whose tools/call goes THROUGH the Ledger (exactly-once within the run).
The mirror image of :ruby_llm — Claude Code owns the loop; Silas hosts the
tools and maps the NDJSON stream onto durable rows.
v1 contract (honestly weaker than :ruby_llm): exactly-once WITHIN a run, approval :never tools only, and fail-closed on mid-subprocess worker kill.
Class Method Summary collapse
Instance Method Summary collapse
Class Method Details
.loop_ownership ⇒ Object
12 |
# File 'lib/silas/engines/agent_sdk.rb', line 12 def self.loop_ownership = :engine |
Instance Method Details
#execute_step(context, &on_event) ⇒ Object
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/silas/engines/agent_sdk.rb', line 14 def execute_step(context, &on_event) turn = context[:turn] Silas::AgentSdk::VersionGuard.assert!(Silas.config.agent_sdk_claude_bin) assert_api_key! tools = allowed_tools(context[:tools]) server = Mcp::Server.start(turn: turn, step: context[:step], tools: tools, resolver: Silas.tool_resolver) cli = nil begin server.await_ready! cli = build_cli(context, server, tools) parser = Silas::AgentSdk::StreamParser.new cli.stream do |line| parser.ingest(line) do |event| persist_session_id!(turn, parser) on_event&.call(event) ActiveSupport::Notifications.instrument("silas.agent_sdk.event", turn_id: turn.id, type: event.type) end end parser.to_result ensure cli&.terminate server.stop end end |