Skip to content

Commit 6a093eb

Browse files
authored
feat: upgrade to slim-bindings ~= 1.1 (#6)
Use latest slim-bindings 1.1.0, which also includes slimrpc implemented natively in rust. Signed-off-by: Mauro Sardara <msardara@cisco.com>
1 parent 1b76063 commit 6a093eb

18 files changed

Lines changed: 1784 additions & 939 deletions

README.md

Lines changed: 224 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -4,75 +4,251 @@ SLIMA2A is a SLIM transport for A2A using slim's RPC protocol (srpc). It allows
44
agents to communicate over the SLIM network using the A2A protocol, using SLIM
55
identities for authentication and addressing.
66

7+
## Compile the protobuf
8+
9+
- Refer to this [documentation](xxx) to download the correct slirpc compiler for your system and make sure to have in in $PATH.
10+
- Install [bufbuild](https://buf.build/docs/cli/installation/)
11+
12+
Run the following from the repo root:
13+
14+
```sh
15+
buf generate
16+
```
17+
718
## Server usage
819

9-
```python
10-
import srpc
20+
### Quick Start (Recommended)
21+
22+
```/dev/null/server_example.py
23+
import asyncio
24+
import slim_bindings
1125
from a2a.server.request_handlers import DefaultRequestHandler
26+
from a2a.server.tasks import InMemoryTaskStore
27+
from slima2a import setup_slim_client
1228
from slima2a.handler import SRPCHandler
13-
from slima2a.types.a2a_pb2_srpc import add_A2AServiceServicer_to_server
29+
from slima2a.types.a2a_pb2_slimrpc import add_A2AServiceServicer_to_server
30+
31+
# Initialize and connect to SLIM (simplified helper)
32+
service, local_app, local_name, conn_id = await setup_slim_client(
33+
namespace="agntcy",
34+
group="demo",
35+
name="echo_agent",
36+
)
1437

38+
# Create request handler
1539
agent_executor = MyAgentExecutor()
40+
task_store = InMemoryTaskStore()
1641
request_handler = DefaultRequestHandler(
17-
agent_executor=agent_executor, task_store=InMemoryTaskStore()
42+
agent_executor=agent_executor,
43+
task_store=task_store,
1844
)
1945

46+
# Create servicer
2047
servicer = SRPCHandler(agent_card, request_handler)
2148

22-
server = srpc.Server(
23-
local="agntcy/demo/server",
24-
slim={
25-
"endpoint": "http://localhost:46357",
26-
"tls": {
27-
"insecure": True,
28-
},
29-
},
30-
shared_secret="secret",
31-
)
32-
33-
a2a_pb2_srpc.add_A2AServiceServicer_to_server(
34-
servicer
35-
server,
36-
)
37-
38-
await server.start()
49+
# Create server
50+
server = slim_bindings.Server.new_with_connection(local_app, local_name, conn_id)
51+
52+
add_A2AServiceServicer_to_server(servicer, server)
53+
54+
# Run server
55+
await server.serve_async()
56+
```
57+
58+
### Advanced Setup (Manual Configuration)
59+
60+
If you need more control over the SLIM configuration:
61+
62+
```/dev/null/server_advanced_example.py
63+
import asyncio
64+
import slim_bindings
65+
from a2a.server.request_handlers import DefaultRequestHandler
66+
from a2a.server.tasks import InMemoryTaskStore
67+
from slima2a.handler import SRPCHandler
68+
from slima2a.types.a2a_pb2_slimrpc import add_A2AServiceServicer_to_server
69+
70+
# Set the event loop for slim_bindings
71+
slim_bindings.slim_bindings.uniffi_set_event_loop(asyncio.get_running_loop())
72+
73+
# Initialize slim_bindings service
74+
tracing_config = slim_bindings.new_tracing_config()
75+
runtime_config = slim_bindings.new_runtime_config()
76+
service_config = slim_bindings.new_service_config()
77+
tracing_config.log_level = "info"
78+
79+
slim_bindings.initialize_with_configs(
80+
tracing_config=tracing_config,
81+
runtime_config=runtime_config,
82+
service_config=[service_config],
83+
)
84+
85+
service = slim_bindings.get_global_service()
86+
87+
# Create local name
88+
local_name = slim_bindings.Name("agntcy", "demo", "echo_agent")
89+
90+
# Connect to SLIM
91+
client_config = slim_bindings.new_insecure_client_config("http://localhost:46357")
92+
conn_id = await service.connect_async(client_config)
93+
94+
# Create app with shared secret
95+
local_app = service.create_app_with_secret(
96+
local_name, "secretsecretsecretsecretsecretsecret"
97+
)
98+
99+
# Subscribe to local name
100+
await local_app.subscribe_async(local_name, conn_id)
101+
102+
# Create request handler
103+
agent_executor = MyAgentExecutor()
104+
task_store = InMemoryTaskStore()
105+
request_handler = DefaultRequestHandler(
106+
agent_executor=agent_executor,
107+
task_store=task_store,
108+
)
109+
110+
# Create servicer
111+
servicer = SRPCHandler(agent_card, request_handler)
112+
113+
# Create server
114+
server = slim_bindings.Server.new_with_connection(local_app, local_name, conn_id)
115+
116+
add_A2AServiceServicer_to_server(servicer, server)
117+
118+
# Run server
119+
await server.serve_async()
39120
```
40121

41122
## Client Usage
42123

43-
```python
44-
from srpc import SRPCChannel
124+
### Quick Start (Recommended)
125+
126+
```/dev/null/client_example.py
127+
import asyncio
128+
import httpx
45129
from a2a.client import ClientFactory, minimal_agent_card
46-
from slima2a.client_transport import SRPCTransport, ClientConfig
47-
48-
def channel_factory(topic) -> SRPCChannel:
49-
channel = srpc.Channel(
50-
local="agntcy/demo/client",
51-
remote="agntcy/demo/server",
52-
slim={
53-
"endpoint": "http://localhost:46357",
54-
"tls": {
55-
"insecure": True,
56-
},
57-
},
58-
shared_secret="secret",
59-
)
60-
return channel
130+
from a2a.types import Message, Part, Role, TextPart
131+
from slima2a import setup_slim_client
132+
from slima2a.client_transport import ClientConfig, SRPCTransport, slimrpc_channel_factory
133+
134+
# Initialize and connect to SLIM (simplified helper)
135+
service, slim_local_app, local_name, conn_id = await setup_slim_client(
136+
namespace="agntcy",
137+
group="demo",
138+
name="client",
139+
)
61140

141+
# Create client config
142+
httpx_client = httpx.AsyncClient()
62143
client_config = ClientConfig(
63-
supported_transports=["JSONRPC", "srpc"],
64-
streaming=args.stream,
144+
supported_transports=["JSONRPC", "slimrpc"],
145+
streaming=True,
65146
httpx_client=httpx_client,
66-
srpc_channel_factory=channel_factory,
147+
slimrpc_channel_factory=slimrpc_channel_factory(slim_local_app, conn_id),
67148
)
149+
150+
# Create client factory and register transport
68151
client_factory = ClientFactory(client_config)
69-
client_factory.register("srpc", SRPCTransport.create)
152+
client_factory.register("slimrpc", SRPCTransport.create)
153+
154+
# Create client with minimal agent card
155+
agent_card = minimal_agent_card("agntcy/demo/echo_agent", ["slimrpc"])
156+
client = client_factory.create(card=agent_card)
157+
158+
# Send message
159+
request = Message(
160+
role=Role.user,
161+
message_id="request-id",
162+
parts=[Part(root=TextPart(text="Hello, world!"))],
163+
)
164+
165+
async for event in client.send_message(request=request):
166+
if isinstance(event, Message):
167+
for part in event.parts:
168+
if isinstance(part.root, TextPart):
169+
print(part.root.text)
170+
```
171+
172+
### Advanced Setup (Manual Configuration)
173+
174+
If you need more control over the SLIM configuration:
175+
176+
```/dev/null/client_advanced_example.py
177+
import asyncio
178+
import httpx
179+
import slim_bindings
180+
from a2a.client import ClientFactory, minimal_agent_card
181+
from a2a.types import Message, Part, Role, TextPart
182+
from slima2a.client_transport import ClientConfig, SRPCTransport, slimrpc_channel_factory
183+
184+
# Set the event loop for slim_bindings
185+
slim_bindings.slim_bindings.uniffi_set_event_loop(asyncio.get_running_loop())
186+
187+
# Initialize slim_bindings service
188+
tracing_config = slim_bindings.new_tracing_config()
189+
runtime_config = slim_bindings.new_runtime_config()
190+
service_config = slim_bindings.new_service_config()
191+
tracing_config.log_level = "info"
192+
193+
slim_bindings.initialize_with_configs(
194+
tracing_config=tracing_config,
195+
runtime_config=runtime_config,
196+
service_config=[service_config],
197+
)
198+
199+
service = slim_bindings.get_global_service()
200+
201+
# Create local name
202+
local_name = slim_bindings.Name("agntcy", "demo", "client")
203+
204+
# Connect to SLIM
205+
client_config_slim = slim_bindings.new_insecure_client_config("http://localhost:46357")
206+
conn_id = await service.connect_async(client_config_slim)
207+
208+
# Create app with shared secret
209+
slim_local_app = service.create_app_with_secret(
210+
local_name, "secretsecretsecretsecretsecretsecret"
211+
)
212+
213+
# Subscribe to local name
214+
await slim_local_app.subscribe_async(local_name, conn_id)
215+
216+
# Create client config
217+
httpx_client = httpx.AsyncClient()
218+
client_config = ClientConfig(
219+
supported_transports=["JSONRPC", "slimrpc"],
220+
streaming=True,
221+
httpx_client=httpx_client,
222+
slimrpc_channel_factory=slimrpc_channel_factory(slim_local_app, conn_id),
223+
)
224+
225+
# Create client factory and register transport
226+
client_factory = ClientFactory(client_config)
227+
client_factory.register("slimrpc", SRPCTransport.create)
228+
229+
# Create client with minimal agent card
230+
agent_card = minimal_agent_card("agntcy/demo/echo_agent", ["slimrpc"])
231+
client = client_factory.create(card=agent_card)
232+
233+
# Send message
234+
request = Message(
235+
role=Role.user,
236+
message_id="request-id",
237+
parts=[Part(root=TextPart(text="Hello, world!"))],
238+
)
239+
240+
async for event in client.send_message(request=request):
241+
if isinstance(event, Message):
242+
for part in event.parts:
243+
if isinstance(part.root, TextPart):
244+
print(part.root.text)
245+
```
246+
247+
## Helper Functions
70248

71-
ac = minimal_agent_card("agntcy/demo/server", ["srpc"])
72-
client = factory.create(ac)
249+
The `slima2a` package provides convenient helper functions to simplify SLIM setup:
73250

74-
try:
75-
response = client.send_message(...)
76-
except srpc.SRPCResponseError as e:
77-
...
251+
- **`setup_slim_client(namespace, group, name, slim_url="http://localhost:46357", secret="...", log_level="info")`** - Complete SLIM client setup in one call
252+
- **`initialize_slim_service(log_level="info")`** - Initialize SLIM service with default configuration
253+
- **`connect_and_subscribe(service, local_name, slim_url="http://localhost:46357", secret="...")`** - Connect to SLIM server and subscribe to a local name
78254
```

buf.gen.yaml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,14 @@
22
version: v2
33
inputs:
44
- git_repo: https://github.com/a2aproject/A2A.git
5-
ref: main
5+
ref: v0.3.0
66
subdir: specification/grpc
77
managed:
88
enabled: true
99
plugins:
1010
# Generate python protobuf related code
1111
# Generates _pb2_slimrpc.py files
12-
13-
# TODO: this should be downloaded from a released plugin version
14-
- local: ../../../target/release/protoc-slimrpc-plugin
12+
- local: protoc-gen-slimrpc-python
1513
out: slima2a/types
1614
opt:
1715
- 'types_import=from a2a.grpc import a2a_pb2 as a2a__pb2'

examples/__init__.py

Whitespace-only changes.

examples/echo_agent/README.md

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,21 @@
11
# Echo Agent
22

33
## Run SLIM node
4+
5+
Download the slimctl version for your system from the [release page.](https://github.com/agntcy/slim/releases/tag/slimctl-v1.0.0)
6+
47
```shell
5-
cd $(git rev-parse --show-toplevel)/data-plane/testing
6-
```
7-
```shell
8-
task run:slim
8+
slimctl slim start --endpoint 127.0.0.1:46357
99
```
1010

1111
## Run echo agent server
12+
1213
```shell
13-
cd $(git rev-parse --show-toplevel)/data-plane/python/integrations/slima2a
14-
```
15-
```shell
16-
uv run examples/echo_agent/server.py
14+
uv run python -m examples.echo_agent.server
1715
```
1816

1917
## Run echo agent client
18+
2019
```shell
21-
cd $(git rev-parse --show-toplevel)/data-plane/python/integrations/slima2a
22-
```
23-
```shell
24-
uv run examples/echo_agent/client.py --text "hi, this is a text message"
20+
uv run python -m examples.echo_agent.client --text "hi, this is a text message"
2521
```

0 commit comments

Comments
 (0)