This document specifies the SLIMRPC custom protocol binding for the Agent2Agent (A2A) protocol.
SLIMRPC is an RPC protocol built on top of SLIM (Secure Low-Latency Interactive Messaging), an open-source communication framework developed by Agntcy. SLIM provides a pub/sub messaging fabric with built-in session and identity management, enabling agents to securely communicate using structured names rather than traditional URLs and ports.
- Underlying Network: SLIM (Secure Low-Latency Interactive Messaging)
- RPC Protocol: SLIMRPC (also referred to as
srpc) - Definition: Uses the same Protocol Buffers definition as the gRPC binding:
specification/a2a.proto - Serialization: Protocol Buffers version 3 (binary encoding)
- Service Name:
a2a.v1.A2AService - Service Parameters: Transmitted as a flat string key-value metadata map alongside each request
- Streaming: SLIM unary-stream RPC pattern (unary request, streaming response)
- Authentication: Provided by the SLIM identity layer (shared secrets or other SLIM-supported mechanisms)
- Transport Identifier:
https://a2a-protocol.org/bindings/experimental-slimrpc/v1(used in Agent CardprotocolBindingfields)
SLIM uses a three-component hierarchical naming scheme instead of URL-based addressing. Every participant in the SLIM network is identified by a Name of the form:
<domain>/<namespace>/<service>
Examples:
| SLIM Name | Description |
|---|---|
mydomain/demo/echo_agent |
An echo agent in the mydomain domain and demo namespace |
mydomain/demo/client |
A client agent in the mydomain domain and demo namespace |
mydomain/production/scheduler |
A scheduler agent in production |
The SLIM Name serves as the service endpoint address in the Agent Card. Clients resolve the agent's Name from the url field of the Agent Card's supportedInterfaces entry where protocolBinding is "https://a2a-protocol.org/bindings/experimental-slimrpc/v1" and where the url uses the domain/namespace/service naming format.
Before exchanging A2A messages, both clients and servers MUST connect to a SLIM node (also called a SLIM broker or gateway). The default SLIM node port is 46357.
Connection flow:
- Initialize the SLIM runtime
- Create a local SLIM identity (App) with a Name and credentials
- Connect to the SLIM node
- Subscribe the App to its own Name so it can receive incoming messages
- For clients: open a Channel to the remote agent's Name
- For servers: register RPC method handlers and begin serving
A Channel is a directional communication handle from a local App to a remote SLIM Name. Clients create a Channel targeting the agent's SLIM Name to issue RPC calls. The channel handles authentication, serialization, framing, and delivery of Protocol Buffer messages over the SLIM network.
A2A service parameters defined in Section 3.2.6 of the specification MUST be transmitted using the SLIMRPC metadata mechanism.
Service Parameter Requirements:
- Service parameters MUST be passed as a flat string key-value metadata map alongside each RPC call
- Service parameter keys are treated as case-insensitive strings in SLIMRPC metadata, consistent with the A2A specification
- Service parameter values are case-sensitive
- Multiple values for the same service parameter (e.g.,
A2A-Extensions) SHOULD be comma-separated in a single metadata entry
Value Constraints:
- Metadata values MUST be UTF-8 encoded strings
- There is no prescribed size limit, but implementations SHOULD keep metadata compact
Reserved Metadata Keys:
SLIMRPC does not reserve any metadata key names for its own use. All keys prefixed with A2A- are reserved for A2A service parameters.
Example service parameters as SLIMRPC metadata:
a2a-version: 1.0
a2a-extensions: https://example.com/extensions/geolocation/v1
On the server side, metadata is extracted from the request context object provided to each handler method.
The SLIMRPC binding exposes the A2AService defined in specification/a2a.proto for the version of A2A being implemented. Client stubs and server handler scaffolding are generated from this proto definition using the SLIMRPC code generator plugin for protoc.
The SLIMRPC binding uses the same Protocol Buffer message types as the gRPC binding. Method names, request types, and response types are determined entirely by the proto definition for the A2A version being targeted — no translation or renaming is applied.
The following table reflects the A2AService methods as defined in the current A2A proto (specification/a2a.proto). Implementations targeting an older version of A2A MUST use the method names, request types, and response types from the proto for that version.
| Method Name | RPC Type | Request Type | Response Type | A2A Operation |
|---|---|---|---|---|
SendMessage |
Unary | SendMessageRequest |
SendMessageResponse |
Send Message |
SendStreamingMessage |
Unary-Stream | SendMessageRequest |
StreamResponse (stream) |
Stream Message |
GetTask |
Unary | GetTaskRequest |
Task |
Get Task |
ListTasks |
Unary | ListTasksRequest |
ListTasksResponse |
List Tasks |
CancelTask |
Unary | CancelTaskRequest |
Task |
Cancel Task |
SubscribeToTask |
Unary-Stream | SubscribeToTaskRequest |
StreamResponse (stream) |
Subscribe to Task |
CreateTaskPushNotificationConfig |
Unary | TaskPushNotificationConfig |
TaskPushNotificationConfig |
Create Push Notification Config |
GetTaskPushNotificationConfig |
Unary | GetTaskPushNotificationConfigRequest |
TaskPushNotificationConfig |
Get Push Notification Config |
ListTaskPushNotificationConfigs |
Unary | ListTaskPushNotificationConfigsRequest |
ListTaskPushNotificationConfigsResponse |
List Push Notification Configs |
DeleteTaskPushNotificationConfig |
Unary | DeleteTaskPushNotificationConfigRequest |
google.protobuf.Empty |
Delete Push Notification Config |
GetExtendedAgentCard |
Unary | GetExtendedAgentCardRequest |
AgentCard |
Get Extended Agent Card |
Sends a message to initiate or continue a task.
Request: SendMessageRequest
Response: SendMessageResponse — contains either a Task or Message
Sends a message and returns a stream of update events. Used when the agent supports streaming (capabilities.streaming = true).
Request: SendMessageRequest
Response: Server-streaming sequence of StreamResponse objects
Retrieves the current state of a task. The name field uses the resource format tasks/{task_id}.
Request: GetTaskRequest
Response: Task
Lists tasks with optional filtering and pagination.
Request: ListTasksRequest
Response: ListTasksResponse
Requests cancellation of an ongoing task. The name field uses the resource format tasks/{task_id}.
Request: CancelTaskRequest
Response: Task
Subscribes to streaming updates for an existing task. Returns UnsupportedOperationError if the task is in a terminal state. The name field uses the resource format tasks/{task_id}.
Request: SubscribeToTaskRequest
Response: Server-streaming sequence of StreamResponse objects
Creates a push notification configuration for a task. Requires capabilities.pushNotifications = true. The parent field uses the resource format tasks/{task_id}.
Request: CreateTaskPushNotificationConfigRequest
Response: TaskPushNotificationConfig
Retrieves a push notification configuration. The name field uses the resource format tasks/{task_id}/pushNotificationConfigs/{config_id}.
Request: GetTaskPushNotificationConfigRequest
Response: TaskPushNotificationConfig
Lists all push notification configurations for a task. The parent field uses the resource format tasks/{task_id}.
Request: ListTaskPushNotificationConfigsRequest
Response: ListTaskPushNotificationConfigsResponse
Removes a push notification configuration. The name field uses the resource format tasks/{task_id}/pushNotificationConfigs/{config_id}.
Request: DeleteTaskPushNotificationConfigRequest
Response: google.protobuf.Empty
Retrieves the agent's extended card after authentication.
Request: GetExtendedAgentCardRequest
Response: AgentCard
SLIMRPC errors use gRPC-compatible status codes (from google.rpc.Code). The error structure carries a numeric status code, a human-readable message string, and optional structured details.
All A2A-specific errors defined in Section 3.3.2 of the specification MUST be mapped to SLIMRPC status codes. The following table defines the canonical mapping:
| A2A Error Type | SLIMRPC Status Code | Notes |
|---|---|---|
JSONParseError |
INTERNAL |
Internal serialization failure |
InvalidRequestError |
INVALID_ARGUMENT |
Malformed or invalid request |
MethodNotFoundError |
UNIMPLEMENTED |
Requested method does not exist |
InvalidParamsError |
INVALID_ARGUMENT |
Method parameters are invalid |
InternalError |
INTERNAL |
Server-side internal error |
TaskNotFoundError |
NOT_FOUND |
Task ID does not exist or is not accessible |
TaskNotCancelableError |
FAILED_PRECONDITION |
Task is in a non-cancelable state |
PushNotificationNotSupportedError |
UNIMPLEMENTED |
Agent does not support push notifications |
UnsupportedOperationError |
UNIMPLEMENTED |
Operation not supported by the agent |
ContentTypeNotSupportedError |
UNIMPLEMENTED |
Content type not accepted by the agent |
InvalidAgentResponseError |
INTERNAL |
Agent produced an unexpected response |
| (unrecognized) | UNKNOWN |
Fallback for unclassified errors |
SLIMRPC errors carry the following fields:
code: Agoogle.rpc.Codeinteger (gRPC-compatible status code)message: A human-readable error description string, prefixed with the A2A error type name (e.g.,"TaskNotFoundError: task-123 not found")details: Optional structured error details
The SLIMRPC binding supports server-streaming via the unary-stream RPC pattern: the client sends a single request message, and the server streams back a sequence of response messages.
SLIMRPC streaming uses a unary request with a streaming response. The stream terminates when:
- The server signals normal completion by closing the stream after all events have been sent
- The server signals an error condition, which the client receives when consuming the stream
- The client cancels the request context
Streaming events are delivered in the order they are produced by the server. Implementations MUST emit events in the correct sequence:
- An initial
TaskorMessagein theStreamResponse - Zero or more
TaskStatusUpdateEventorTaskArtifactUpdateEventupdates - A
TaskStatusUpdateEventcarrying a terminal state (completed,failed,canceled,rejected) or an interrupted state (input_required,auth_required), at which point the server closes the stream
- Normal termination: The server closes the stream after emitting a terminal or interrupted state event
- Error termination: The server sends a status error on the stream; the client receives it as an error when consuming the stream
- Client channel close: The client closes the SLIM channel, terminating the stream. The underlying task continues executing on the server; clients MAY reconnect using
SubscribeToTaskto resume receiving events - Deadline exceeded: If a deadline is configured on the request, the stream is terminated when that deadline is reached. As with a channel close, the underlying task is not affected
If a streaming connection is interrupted, clients SHOULD use the SubscribeToTask method to resubscribe to an in-progress task using the task ID obtained from the initial response. Implementations SHOULD tolerate duplicate events that may result from reconnection.
Agents that support streaming MUST declare capabilities.streaming = true in their Agent Card. The SendStreamingMessage and SubscribeToTask methods MUST return UnsupportedOperationError if streaming is not enabled.
SLIMRPC leverages SLIM built-in identity and authentication layer. Every SLIM App is associated with a Name and a credential (shared secrets or other SLIM-supported schemes such as mTLS).
Authentication is established at the SLIM network layer before any A2A messages are exchanged:
- Both the client and server establish SLIM App identities with their respective Names and credentials
- The SLIM node authenticates both parties during connection and subscription
- Subsequent RPC calls inherit the established SLIM identity context
As a result, A2A-level authentication headers (e.g., Authorization: Bearer …) are not required when using the SLIMRPC binding — the SLIM network provides the authentication guarantee.
SLIM credentials are configured when creating a SLIM App identity and are not transmitted in individual RPC request metadata. Credential management is handled entirely by the SLIM runtime.
Each RPC handler receives a request context that carries the authenticated caller's SLIM identity. Implementations MAY use this to perform additional authorization checks before processing the request.
When using the SLIMRPC binding, agents SHOULD document in their Agent Card that authentication is provided by the SLIM network layer. The securitySchemes field MAY include a reference to SLIM identity, or may be omitted if no additional application-level authentication is required.
Agents that support the SLIMRPC binding MUST declare it in their Agent Card using the supportedInterfaces field.
Agent Card requirements for SLIMRPC:
url: The agent's SLIM Name as aslim://URL inslim://[node-host[:port]/]domain/namespace/serviceformat. Two forms are supported:slim://domain/namespace/service— when the SLIM node is managed by a controller or configured out-of-bandslim://node.example.com:46357/domain/namespace/service— when the node address needs to be explicitly specified
protocolBinding: Set to"https://a2a-protocol.org/bindings/experimental-slimrpc/v1"
Example Agent Card fragment:
{
"name": "Echo Agent",
"url": "slim://domain/demo/echo_agent",
"supportedInterfaces": [
{
"url": "slim://domain/demo/echo_agent",
"protocolBinding": "https://a2a-protocol.org/bindings/experimental-slimrpc/v1"
}
],
"capabilities": {
"streaming": true,
"pushNotifications": false
}
}Multi-binding example (agent supporting both JSON-RPC and SLIMRPC):
{
"name": "Travel Planner Agent",
"url": "https://agent.example.com",
"supportedInterfaces": [
{
"url": "https://agent.example.com/rpc",
"protocolBinding": "JSONRPC"
},
{
"url": "slim://node.example.com:46357/domain/production/travel_planner",
"protocolBinding": "https://a2a-protocol.org/bindings/experimental-slimrpc/v1"
}
]
}The SLIMRPC binding uses Protocol Buffer binary serialization. All A2A data types are represented exactly as defined in specification/a2a.proto, identical to the gRPC binding.
| A2A Data Type | Wire Representation |
|---|---|
| Messages | Protocol Buffer binary encoding |
| Timestamps | google.protobuf.Timestamp (seconds + nanoseconds) |
| Binary data | bytes field — raw binary, no base64 encoding needed |
| Enumerations | Protocol Buffer enum integer wire values |
| Optional fields | Protocol Buffer optional / oneof semantics |
Timestamps are encoded natively as google.protobuf.Timestamp; ISO 8601 string encoding is not required, unlike JSON-based bindings. Binary content is transmitted as raw bytes with no base64 wrapping.