calfkit 0.1.1__py3-none-any.whl → 0.1.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,7 @@
1
+ from collections.abc import Awaitable, Callable
1
2
  from typing import Any
2
3
 
3
- from faststream import BaseMiddleware
4
+ from faststream import BaseMiddleware, PublishCommand
4
5
  from faststream.message import StreamMessage
5
6
  from faststream.types import AsyncFuncAny
6
7
 
@@ -13,3 +14,10 @@ class ContextInjectionMiddleware(BaseMiddleware):
13
14
  ) -> Any:
14
15
  with self.context.scope("correlation_id", msg.correlation_id):
15
16
  return await super().consume_scope(call_next, msg)
17
+
18
+ async def publish_scope(
19
+ self,
20
+ call_next: Callable[[PublishCommand], Awaitable[Any]],
21
+ cmd: PublishCommand,
22
+ ) -> Any:
23
+ return await call_next(cmd)
calfkit/models/types.py CHANGED
@@ -57,6 +57,7 @@ class CompactBaseModel(BaseModel):
57
57
  def model_dump(self, **kwargs: Any) -> dict[str, Any]:
58
58
  kwargs.setdefault("exclude_unset", True)
59
59
  kwargs.setdefault("exclude_none", True)
60
+ kwargs.setdefault("mode", "json") # Converts datetime, etc. to JSON-serializable types
60
61
  return super().model_dump(**kwargs)
61
62
 
62
63
  def model_dump_json(self, **kwargs: Any) -> str:
@@ -1,4 +1,4 @@
1
- from typing import Annotated, Any
1
+ from typing import Annotated, Any, overload
2
2
 
3
3
  import uuid_utils
4
4
  from faststream import Context
@@ -23,16 +23,84 @@ class AgentRouterNode(BaseNode):
23
23
  _router_sub_topic_name = "agent_router.input"
24
24
  _router_pub_topic_name = "agent_router.output"
25
25
 
26
+ @overload
26
27
  def __init__(
27
28
  self,
28
29
  chat_node: BaseNode,
30
+ *,
31
+ system_prompt: str,
29
32
  tool_nodes: list[BaseToolNode],
33
+ handoff_nodes: list[type[BaseNode]] = [],
34
+ message_history_store: MessageHistoryStore,
35
+ **kwargs: Any,
36
+ ): ...
37
+
38
+ @overload
39
+ def __init__(
40
+ self,
41
+ chat_node: BaseNode,
42
+ *,
30
43
  system_prompt: str | None = None,
44
+ tool_nodes: list[BaseToolNode] = [],
45
+ handoff_nodes: list[type[BaseNode]] = [],
46
+ message_history_store: MessageHistoryStore | None = None,
47
+ **kwargs: Any,
48
+ ): ...
49
+
50
+ @overload
51
+ def __init__(self) -> None: ...
52
+
53
+ @overload
54
+ def __init__(
55
+ self,
56
+ *,
57
+ system_prompt: str | None = None,
58
+ tool_nodes: list[BaseToolNode] = [],
59
+ handoff_nodes: list[type[BaseNode]] = [],
60
+ ): ...
61
+
62
+ def __init__(
63
+ self,
64
+ chat_node: BaseNode | None = None,
65
+ *,
66
+ system_prompt: str | None = None,
67
+ tool_nodes: list[BaseToolNode] = [],
31
68
  handoff_nodes: list[type[BaseNode]] = [],
32
69
  message_history_store: MessageHistoryStore | None = None,
33
- *args: Any,
34
70
  **kwargs: Any,
35
71
  ):
72
+ """Initialize an AgentRouterNode.
73
+
74
+ The AgentRouterNode supports multiple initialization patterns depending on use case:
75
+
76
+ 1. **Deployable Router Service** (with required parameters):
77
+ Use when deploying the router as a service with all dependencies explicitly provided.
78
+ Requires: chat_node, system_prompt (str), tool_nodes, message_history_store
79
+
80
+ 2. **Deployable Router Service** (with optional parameters):
81
+ Use when deploying with optional or runtime-configurable dependencies.
82
+ Requires: chat_node
83
+ Optional: system_prompt, tool_nodes, handoff_nodes, message_history_store
84
+
85
+ 3. **Minimal Client**:
86
+ Use when creating a client to invoke an already-deployed router service.
87
+ No parameters needed - connects to the deployed service via the broker.
88
+
89
+ 4. **Client with Runtime Patches**:
90
+ Use when creating a client that provides its own tools/system prompt at runtime,
91
+ overriding or supplementing what the deployed router service provides.
92
+ Optional: system_prompt, tool_nodes, handoff_nodes
93
+
94
+ Args:
95
+ chat_node: The chat node for LLM interactions. Required for deployable services.
96
+ system_prompt: Optional system prompt to override the default. Must be str for
97
+ deployable service, optional for client with runtime patches.
98
+ tool_nodes: List of tool nodes that the agent can call. Optional for all forms.
99
+ handoff_nodes: List of node types for agent handoff scenarios. Optional.
100
+ message_history_store: Store for persisting conversation history across requests.
101
+ Required for deployable service, optional otherwise.
102
+ **kwargs: Additional keyword arguments passed to BaseNode.
103
+ """
36
104
  self.chat = chat_node
37
105
  self.tools = tool_nodes
38
106
  self.handoffs = handoff_nodes
@@ -52,7 +120,7 @@ class AgentRouterNode(BaseNode):
52
120
 
53
121
  self.tool_response_topics = [tool.publish_to_topic for tool in self.tools]
54
122
 
55
- super().__init__(*args, **kwargs)
123
+ super().__init__(**kwargs)
56
124
 
57
125
  @subscribe_to(_router_sub_topic_name)
58
126
  @publish_to(_router_pub_topic_name)
@@ -148,7 +216,7 @@ class AgentRouterNode(BaseNode):
148
216
  )
149
217
  await broker.publish(
150
218
  event_envelope,
151
- topic=self.chat.subscribed_topic,
219
+ topic=self.chat.subscribed_topic, # type: ignore
152
220
  correlation_id=correlation_id,
153
221
  reply_to=self.subscribed_topic,
154
222
  )
@@ -172,12 +240,16 @@ class AgentRouterNode(BaseNode):
172
240
  Returns:
173
241
  str: The correlation ID for this request
174
242
  """
175
- patch_model_request_params = ModelRequestParameters(
176
- function_tools=[tool.tool_schema() for tool in self.tools]
243
+
244
+ patch_model_request_params = (
245
+ ModelRequestParameters(function_tools=[tool.tool_schema() for tool in self.tools])
246
+ if self.tools
247
+ else None
177
248
  )
178
249
  if correlation_id is None:
179
250
  correlation_id = uuid_utils.uuid7().hex
180
251
  new_node_messages = [ModelRequest.user_text_prompt(user_prompt)]
252
+ await broker.start()
181
253
  await broker.publish(
182
254
  EventEnvelope(
183
255
  kind="user_prompt",
@@ -0,0 +1,192 @@
1
+ Metadata-Version: 2.4
2
+ Name: calfkit
3
+ Version: 0.1.2
4
+ Summary: Event-driven SDK for building AI workflows on Kafka
5
+ Project-URL: Homepage, https://github.com/calf-ai/calf-sdk
6
+ Project-URL: Repository, https://github.com/calf-ai/calf-sdk
7
+ Project-URL: Issues, https://github.com/calf-ai/calf-sdk/issues
8
+ Author: Ryan Yu
9
+ License-Expression: Apache-2.0
10
+ License-File: LICENSE
11
+ Keywords: agents,ai,decoupled,distributed,event-driven,kafka,llm,workflows
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: Apache Software License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Requires-Python: >=3.10
21
+ Requires-Dist: faststream[kafka]>=0.6.6
22
+ Requires-Dist: pydantic-ai>=1.47.0
23
+ Requires-Dist: pydantic>=2.12.5
24
+ Requires-Dist: python-dotenv>=1.2.1
25
+ Requires-Dist: uuid-utils>=0.14.0
26
+ Provides-Extra: dev
27
+ Description-Content-Type: text/markdown
28
+
29
+ # Calfkit SDK
30
+
31
+ The SDK to build AI agents that scale. Calfkit lets you compose agents from independent services—chat, tools, routing—that communicate through events, not API calls. Add capabilities without coordination. Scale each component independently. Stream agent outputs to any downstream system.
32
+
33
+ ## Why Event-Driven Agents?
34
+
35
+ Building agents like traditional web applications—with tight coupling and direct API calls—creates the same scalability problems that plagued early microservices.
36
+
37
+ When agents connect through APIs and RPC:
38
+ - **Tight coupling** — Changing one tool breaks dependent agents
39
+ - **Scaling bottlenecks** — Everything must scale together
40
+ - **Siloed outputs** — Agent responses stay trapped in your AI layer
41
+
42
+ Event-driven architecture provides the solution. Instead of direct API calls between components, agents interact through asynchronous event streams. Each component runs independently, scales horizontally, and outputs can flow anywhere—CRMs, data warehouses, analytics platforms, other agents.
43
+
44
+ ## Why use Calfkit?
45
+
46
+ Calfkit is a Python SDK that makes event-driven agents simple. You get the benefits of a distributed system—loose coupling, horizontal scalability, durability—without the complexity of managing Kafka infrastructure yourself.
47
+
48
+ - **Distributed agents out of the box** — Build event-driven, multi-service agents without writing orchestration code or managing infrastructure
49
+ - **Add tools without touching existing code** — Deploy new capabilities as independent services that other agents discover automatically
50
+ - **Scale what you need, when you need it** — Chat handling, tool execution, and routing each scale independently based on demand
51
+ - **Nothing gets lost** — Event persistence ensures reliable message delivery—even during failures or restarts
52
+ - **Real-time responses** — Low-latency event processing enables agents to react instantly to incoming data
53
+ - **Team independence** — Different teams can develop and deploy chat, tools, and routing concurrently without coordination overhead
54
+ - **Universal data flow** — Decoupling enables data to flow freely in both directions. Downstream, agent outputs integrate with any system (CRMs, CDPs, warehouses). Upstream, tools wrap data sources and deploy independently—no coordination needed.
55
+
56
+ ## Quick Start
57
+
58
+ ### Prerequisites
59
+
60
+ ```bash
61
+ # Kafka (single command via Docker)
62
+ docker run -d -p 9092:9092 apache/kafka:latest
63
+
64
+ # Python 3.10+
65
+ python --version
66
+
67
+ # OpenAI API key
68
+ export OPENAI_API_KEY=sk-...
69
+ ```
70
+
71
+ ### Install
72
+
73
+ ```bash
74
+ pip install git+https://github.com/calf-ai/calf-sdk.git
75
+ ```
76
+
77
+ ### Deploy the Tool Node
78
+
79
+ Define and deploy a tool as an independent service.
80
+
81
+ ```python
82
+ import asyncio
83
+ from calfkit.nodes import agent_tool
84
+ from calfkit.broker import Broker
85
+ from calfkit.runners import ToolRunner
86
+
87
+ @agent_tool
88
+ def get_weather(location: str) -> str:
89
+ """Get the current weather at a location"""
90
+ return f"It's sunny in {location}"
91
+
92
+ async def main():
93
+ broker = Broker(bootstrap_servers="localhost:9092")
94
+ ToolRunner(get_weather).register_on(broker)
95
+ await broker.run_app()
96
+
97
+ asyncio.run(main())
98
+ ```
99
+
100
+ ### Deploy the Chat Node
101
+
102
+ Deploy the LLM chat handler as its own service.
103
+
104
+ ```python
105
+ import asyncio
106
+ from calfkit.nodes import ChatNode
107
+ from calfkit.providers import OpenAIModelClient
108
+ from calfkit.broker import Broker
109
+ from calfkit.runners import ChatRunner
110
+
111
+ async def main():
112
+ broker = Broker(bootstrap_servers="localhost:9092")
113
+ model_client = OpenAIModelClient(model_name="gpt-5-nano")
114
+ chat_node = ChatNode(model_client)
115
+ ChatRunner(chat_node).register_on(broker)
116
+ await broker.run_app()
117
+
118
+ asyncio.run(main())
119
+ ```
120
+
121
+ ### Deploy the Agent Router Node
122
+
123
+ Deploy the router that orchestrates chat and tools.
124
+
125
+ ```python
126
+ import asyncio
127
+ from calfkit.nodes import agent_tool, AgentRouterNode, ChatNode
128
+ from calfkit.providers import OpenAIModelClient
129
+ from calfkit.stores import InMemoryMessageHistoryStore
130
+ from calfkit.broker import Broker
131
+ from calfkit.runners import AgentRouterRunner
132
+
133
+ @agent_tool
134
+ def get_weather(location: str) -> str:
135
+ """Get the current weather at a location"""
136
+ return f"It's sunny in {location}"
137
+
138
+ async def main():
139
+ broker = Broker(bootstrap_servers="localhost:9092")
140
+ model_client = OpenAIModelClient(model_name="gpt-4o")
141
+ router_node = AgentRouterNode(
142
+ chat_node=ChatNode(model_client),
143
+ tool_nodes=[get_weather],
144
+ system_prompt="You are a helpful assistant",
145
+ message_history_store=InMemoryMessageHistoryStore(),
146
+ )
147
+ AgentRouterRunner(router_node).register_on(broker)
148
+ await broker.run_app()
149
+
150
+ asyncio.run(main())
151
+ ```
152
+
153
+ ### Invoke the Agent
154
+
155
+ Send a request and receive the response.
156
+
157
+ ```python
158
+ import asyncio
159
+ from calfkit.nodes import agent_tool, AgentRouterNode, ChatNode
160
+ from calfkit.providers import OpenAIModelClient
161
+ from calfkit.stores import InMemoryMessageHistoryStore
162
+ from calfkit.broker import Broker
163
+
164
+ @agent_tool
165
+ def get_weather(location: str) -> str:
166
+ """Get the current weather at a location"""
167
+ return f"It's sunny in {location}"
168
+
169
+ async def main():
170
+ broker = Broker(bootstrap_servers="localhost:9092")
171
+ model_client = OpenAIModelClient(model_name="gpt-5-nano")
172
+
173
+ router_node = AgentRouterNode(
174
+ chat_node=ChatNode(model_client),
175
+ tool_nodes=[get_weather],
176
+ system_prompt="You are a helpful assistant",
177
+ message_history_store=InMemoryMessageHistoryStore(),
178
+ )
179
+
180
+ correlation_id = await router_node.invoke(
181
+ user_prompt="What's the weather in Tokyo?",
182
+ broker=broker,
183
+ final_response_topic="final_response",
184
+ )
185
+ print(f"Request started: {correlation_id}")
186
+
187
+ asyncio.run(main())
188
+ ```
189
+
190
+ ## License
191
+
192
+ Apache-2.0
@@ -2,14 +2,14 @@ calfkit/__init__.py,sha256=TNjZ-vfuYWSFldFQniKQvb0XRB55YzNqgLHyAKQcYrg,99
2
2
  calfkit/broker/__init__.py,sha256=35HCFxzWmmh0hhBf7bf7Ix7XPUJaS-GQjAKwDpZ-EnI,63
3
3
  calfkit/broker/broker.py,sha256=9s8RbkxItA5NcuQX6U7lXqaL2WYrQ8JIZAusD_YARxs,996
4
4
  calfkit/broker/deployable.py,sha256=mzvYllCbh4m3lMCdbMsVlOyQ2jTHlx92RYjkHgry1zQ,122
5
- calfkit/broker/middleware.py,sha256=X9Ta4gLYkivOTTNjLzDXNIJSwLPUOlojvz2SmxgIHco,458
5
+ calfkit/broker/middleware.py,sha256=_j_gz88ADeAQDXMlf8V0yR5lZi5CsG-D43abinfK9yA,708
6
6
  calfkit/experimental/rpc_worker.py,sha256=_FeUmcS4aFY4IRaz-qrMelFXCGNKdEySE0BSWTOzudE,1439
7
7
  calfkit/messages/__init__.py,sha256=4Wv45OrQMI0opPK70D1IyysbjxwdxJP4y56PkkEEtq0,309
8
8
  calfkit/messages/util.py,sha256=EamqjS74LlHRBzOgER5o2VWwQFkcxt9Kwtd6QE4pqNw,3295
9
9
  calfkit/models/event_envelope.py,sha256=zd10sQ51LgqxroZsxrm3kNkB5hWRtou73iLRdWeig6Y,1607
10
- calfkit/models/types.py,sha256=PQBJFeiwsoY5najanNkL6IymM3mZYv2voFQR9smcObs,1989
10
+ calfkit/models/types.py,sha256=WGaljolkj06u_-OvMDbyIC_2fv8sg2qJ8j7fJSGKaRs,2085
11
11
  calfkit/nodes/__init__.py,sha256=nWU-r76xj_cxQ9W6RXs5IDhvXAwsMDAVrx_ZuxRmLgI,457
12
- calfkit/nodes/agent_router_node.py,sha256=Zo1jApqLdnm2BPQD101Ay9UUVwSg2ADBRFti9V5Ts8A,7362
12
+ calfkit/nodes/agent_router_node.py,sha256=DDF0Yjh7RnaNFLTQly5IZkv8d78a0wcVDq2XTuAsaaI,10181
13
13
  calfkit/nodes/base_node.py,sha256=sEynWeQejGV-jmConBTY09fMIfTsnYnvtCIYZOp-vlk,2147
14
14
  calfkit/nodes/base_tool_node.py,sha256=t1epxURAkGiqSCcnmPp1f41TacF9mwYnuShngX_7hfQ,2000
15
15
  calfkit/nodes/chat_node.py,sha256=F3pBvJxiKcWNdviGtpYtWZFQn3ffc4Ka-mh8yIBw_PQ,1943
@@ -22,7 +22,7 @@ calfkit/runners/node_runner.py,sha256=bJ8wk4gPADX2ctmyoXgslwGItOxG2fH2MKk3ORPtLN
22
22
  calfkit/stores/__init__.py,sha256=JIaqYv5OnddLdf3l3KO6ET2Wsd0sOGwxIFiUPRjKn_U,1167
23
23
  calfkit/stores/base.py,sha256=hPR0V2HAzrOGO5HNUfZSQ82YEoCKKHfY3EQVpHODpa0,1900
24
24
  calfkit/stores/in_memory.py,sha256=ZKGfPdLUxri8Q3otzVsWqaDYFYvDpBjYgWRDRoF2C70,1002
25
- calfkit-0.1.1.dist-info/METADATA,sha256=tG8BXjPadC5KFUz8vsLzEQYxzH0jxGKAe_5TYxs0WY4,5018
26
- calfkit-0.1.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
27
- calfkit-0.1.1.dist-info/licenses/LICENSE,sha256=nSECZEo9kht4X50TajtlnrVg21bXN4PVs5mSi5ihAGs,11338
28
- calfkit-0.1.1.dist-info/RECORD,,
25
+ calfkit-0.1.2.dist-info/METADATA,sha256=0Df_4L6n-xbIATJEI7j8-7TyouG-aU4-MrKi-aRnVMQ,6847
26
+ calfkit-0.1.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
27
+ calfkit-0.1.2.dist-info/licenses/LICENSE,sha256=nSECZEo9kht4X50TajtlnrVg21bXN4PVs5mSi5ihAGs,11338
28
+ calfkit-0.1.2.dist-info/RECORD,,
@@ -1,129 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: calfkit
3
- Version: 0.1.1
4
- Summary: Event-driven SDK for building AI workflows on Kafka
5
- Project-URL: Homepage, https://github.com/calf-ai/calf-sdk
6
- Project-URL: Repository, https://github.com/calf-ai/calf-sdk
7
- Project-URL: Issues, https://github.com/calf-ai/calf-sdk/issues
8
- Author: Ryan Yu
9
- License-Expression: Apache-2.0
10
- License-File: LICENSE
11
- Keywords: agents,ai,event-driven,kafka,llm,workflows
12
- Classifier: Development Status :: 3 - Alpha
13
- Classifier: Intended Audience :: Developers
14
- Classifier: License :: OSI Approved :: Apache Software License
15
- Classifier: Programming Language :: Python :: 3
16
- Classifier: Programming Language :: Python :: 3.10
17
- Classifier: Programming Language :: Python :: 3.11
18
- Classifier: Programming Language :: Python :: 3.12
19
- Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
- Requires-Python: >=3.10
21
- Requires-Dist: faststream[cli]>=0.6.0
22
- Requires-Dist: pydantic-ai>=1.47.0
23
- Requires-Dist: pydantic>=2.12.5
24
- Requires-Dist: python-dotenv>=1.2.1
25
- Requires-Dist: uuid-utils>=0.14.0
26
- Provides-Extra: dev
27
- Description-Content-Type: text/markdown
28
-
29
- # Calf SDK
30
-
31
- Event-driven AI agents that scale like microservices. Build loosely-coupled, distributed agent systems where tools, chats, and workflows each run as independent services—communicating through events.
32
-
33
- ## Why Event-Driven Agents?
34
-
35
- Building agents like traditional web applications—with tight coupling and direct API calls—creates the same scalability problems that plagued early microservices.
36
-
37
- When agents connect through APIs and RPC:
38
- - **Tight coupling** — Changing one tool breaks dependent agents
39
- - **Scaling bottlenecks** — Everything must scale together
40
- - **Siloed outputs** — Agent responses stay trapped in your AI layer
41
-
42
- Event-driven architecture provides the solution. Instead of direct API calls between components, agents interact through asynchronous event streams. Each component runs independently, scales horizontally, and outputs can flow anywhere—CRMs, data warehouses, analytics platforms, other agents.
43
-
44
- ## What Calf Gives You
45
-
46
- Calf is a Python SDK that makes event-driven agents simple. You get the benefits of a distributed system—loose coupling, horizontal scalability, durability—without the complexity of managing Kafka infrastructure yourself.
47
-
48
- | Benefit | What It Means for You |
49
- |---------|----------------------|
50
- | **Add tools without touching existing code** | Deploy new capabilities as independent services that other agents discover automatically |
51
- | **Scale what you need, when you need it** | Chat handling, tool execution, and routing each scale independently based on demand |
52
- | **Nothing gets lost** | Event persistence ensures reliable message delivery—even during failures or restarts |
53
- | **Real-time responses** | Low-latency event processing enables agents to react instantly to incoming data |
54
- | **Team independence** | Different teams can develop and deploy chat, tools, and routing concurrently without coordination overhead |
55
- | **Universal data flow** | Decoupling enables data to flow freely in both directions. Downstream, agent outputs integrate with any system (CRMs, CDPs, warehouses). Upstream, tools wrap data sources and deploy independently—no coordination needed. |
56
-
57
- ## Quick Start
58
-
59
- ### Prerequisites
60
-
61
- ```bash
62
- # Kafka (single command via Docker)
63
- docker run -d -p 9092:9092 apache/kafka:latest
64
-
65
- # Python 3.10+
66
- python --version
67
-
68
- # OpenAI API key
69
- export OPENAI_API_KEY=sk-...
70
- ```
71
-
72
- ### Install
73
-
74
- ```bash
75
- pip install git+https://github.com/calf-ai/calf-sdk.git
76
- ```
77
-
78
- ### Create and Run an Agent
79
-
80
- ```python
81
- import asyncio
82
- from calfkit.nodes import agent_tool, AgentRouterNode, ChatNode
83
- from calfkit.providers import OpenAIModelClient
84
- from calfkit.stores import InMemoryMessageHistoryStore
85
- from calfkit.broker import Broker
86
- from calfkit.runners import ChatRunner, ToolRunner, AgentRouterRunner
87
-
88
- # 1. Define a tool
89
- @agent_tool
90
- def get_weather(location: str) -> str:
91
- """Get the current weather at a location"""
92
- return f"It's sunny in {location}"
93
-
94
- # 2. Setup broker and nodes
95
- async def main():
96
- broker = Broker(bootstrap_servers="localhost:9092")
97
- model_client = OpenAIModelClient(model_name="gpt-4o")
98
-
99
- # Deploy chat node
100
- chat_node = ChatNode(model_client)
101
- ChatRunner(chat_node).register_on(broker)
102
-
103
- # Deploy tool node
104
- ToolRunner(get_weather).register_on(broker)
105
-
106
- # Deploy router node
107
- router_node = AgentRouterNode(
108
- chat_node=ChatNode(model_client),
109
- tool_nodes=[get_weather],
110
- system_prompt="You are a helpful assistant",
111
- message_history_store=InMemoryMessageHistoryStore(),
112
- )
113
- AgentRouterRunner(router_node).register_on(broker)
114
-
115
- # Run broker and invoke
116
- await broker.run_app()
117
- correlation_id = await router_node.invoke(
118
- user_prompt="What's the weather in Tokyo?",
119
- broker=broker,
120
- final_response_topic="final_response",
121
- )
122
- print(f"Request started: {correlation_id}")
123
-
124
- asyncio.run(main())
125
- ```
126
-
127
- ## License
128
-
129
- Apache-2.0