Agent Client Protocol Ruby
Ruby helpers for implementing the Agent Client Protocol (ACP).
Community version (unofficial): this repository is not the official ACP Ruby SDK and is not maintained by the ACP core maintainers.
This project references the canonical ACP schema from ../agent-client-protocol and provides:
- ACP method constants (stable + unstable)
- Protocol version parsing behavior compatible with ACP
- JSON-RPC 2.0 request/response/notification models
- Side-aware request/notification decoding by method name
- Generated typed model classes from ACP schema definitions
- Strict JSON Schema validation for ACP payloads
- End-to-end codec helpers for RPC parsing/encoding + typed decode
- Protocol-level notifications (e.g.
$/cancel_request, unstable) - Enum convenience constants (
ToolKind::READ,ToolCallStatus::COMPLETED, etc.)
Install
Add to your Gemfile:
gem "agent-client-protocol", "~> 0.1"
For local development against the source checkout:
gem "agent-client-protocol", path: "/path/to/agent-client-protocol-ruby"
Quick Start
require "agent_client_protocol"
decoder = AgentClientProtocol::Decoder.new(side: :agent)
decoded = decoder.decode_request(method: "initialize", params: {
"protocolVersion" => 1,
"clientCapabilities" => {}
})
puts decoded.schema_name
# => "InitializeRequest"
puts decoded.typed_payload.class
# => AgentClientProtocol::Types::InitializeRequest
Typed classes are available by schema definition name:
klass = AgentClientProtocol.type_for("InitializeRequest")
payload = klass.build(protocol_version: 1, client_capabilities: {})
payload.protocol_version # => 1
payload.to_h # => {"protocolVersion"=>1, "clientCapabilities"=>{}}
Referenced nested schema fields are also coerced to typed models (including scalar wrappers such as ProtocolVersion).
Legacy protocol version strings are accepted and coerced to version 0 (matching official ACP behavior).
Enum Constants
Common enum values are available as Ruby constants:
AgentClientProtocol::ToolKind::READ # => "read"
AgentClientProtocol::ToolCallStatus::PENDING # => "pending"
AgentClientProtocol::PlanEntryStatus::COMPLETED # => "completed"
AgentClientProtocol::StopReason::END_TURN # => "end_turn"
AgentClientProtocol::Role::ASSISTANT # => "assistant"
Validation
Payloads are schema-validated during decode by default. You can also validate directly:
AgentClientProtocol.validate("InitializeRequest", {
"protocolVersion" => 1,
"clientCapabilities" => {}
})
# => true
Codec
Codec helpers provide end-to-end JSON-RPC message handling:
codec = AgentClientProtocol.codec(side: :agent)
request = codec.encode_request(
method: "initialize",
id: "req-1",
params: { "protocolVersion" => 1, "clientCapabilities" => {} }
)
decoded = codec.decode_rpc(request)
decoded.typed_payload.class # => AgentClientProtocol::Types::InitializeRequest
Scope
This is a schema-driven Ruby runtime implementation. It dynamically generates one Ruby class per ACP schema definition at runtime.
Optional / Undefined Fields
Some ACP types (especially unstable ones) distinguish between a field being absent (undefined), explicitly null, and having a value. In the official Rust SDK this is modeled as MaybeUndefined<T>.
In Ruby, absent keys in the underlying attribute Hash represent "undefined", nil values represent JSON null, and all other values represent present data. Use key? to distinguish absent from null:
obj.key?(:title) # false => undefined (field was not sent)
obj[:title] # nil => could be null OR absent; use key? to tell apart
Syncing With Upstream Schema
./scripts/sync_schema.sh
You can also pass a custom source directory:
./scripts/sync_schema.sh /path/to/agent-client-protocol/schema