Skip to content

Commit e72b7ea

Browse files
committed
better tool response formatting
1 parent 2c56c6d commit e72b7ea

File tree

13 files changed

+2127
-12
lines changed

13 files changed

+2127
-12
lines changed
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": 2,
6+
"id": "36834357",
7+
"metadata": {},
8+
"outputs": [],
9+
"source": [
10+
"from agentex import Agentex\n",
11+
"\n",
12+
"client = Agentex(base_url=\"http://localhost:5003\")"
13+
]
14+
},
15+
{
16+
"cell_type": "code",
17+
"execution_count": 3,
18+
"id": "d1c309d6",
19+
"metadata": {},
20+
"outputs": [],
21+
"source": [
22+
"AGENT_NAME = \"s000-hello-acp\""
23+
]
24+
},
25+
{
26+
"cell_type": "code",
27+
"execution_count": 4,
28+
"id": "9f6e6ef0",
29+
"metadata": {},
30+
"outputs": [],
31+
"source": [
32+
"# # (Optional) Create a new task. If you don't create a new task, each message will be sent to a new task. The server will create the task for you.\n",
33+
"\n",
34+
"# import uuid\n",
35+
"\n",
36+
"# TASK_ID = str(uuid.uuid4())[:8]\n",
37+
"\n",
38+
"# rpc_response = client.agents.rpc_by_name(\n",
39+
"# agent_name=AGENT_NAME,\n",
40+
"# method=\"task/create\",\n",
41+
"# params={\n",
42+
"# \"name\": f\"{TASK_ID}-task\",\n",
43+
"# \"params\": {}\n",
44+
"# }\n",
45+
"# )\n",
46+
"\n",
47+
"# task = rpc_response.result\n",
48+
"# print(task)"
49+
]
50+
},
51+
{
52+
"cell_type": "code",
53+
"execution_count": 5,
54+
"id": "b03b0d37",
55+
"metadata": {},
56+
"outputs": [
57+
{
58+
"name": "stdout",
59+
"output_type": "stream",
60+
"text": [
61+
"Hello! I've received your message. Here's a generic response, but in future tutorials we'll see how you can get me to intelligently respond to your message. This is what I heard you say: Hello what can you do?\n"
62+
]
63+
}
64+
],
65+
"source": [
66+
"# Test non streaming response\n",
67+
"from typing import List, cast\n",
68+
"from agentex.types import TaskMessage, TextContent\n",
69+
"\n",
70+
"# The response is expected to be a list of TaskMessage objects, which is a union of the following types:\n",
71+
"# - TextContent: A message with just text content \n",
72+
"# - DataContent: A message with JSON-serializable data content\n",
73+
"# - ToolRequestContent: A message with a tool request, which contains a JSON-serializable request to call a tool\n",
74+
"# - ToolResponseContent: A message with a tool response, which contains response object from a tool call in its content\n",
75+
"\n",
76+
"# When processing the message/send response, if you are expecting more than TextContent, such as DataContent, ToolRequestContent, or ToolResponseContent, you can process them as well\n",
77+
"\n",
78+
"rpc_response = client.agents.rpc_by_name(\n",
79+
" agent_name=AGENT_NAME,\n",
80+
" method=\"message/send\",\n",
81+
" params={\n",
82+
" \"content\": {\"type\": \"text\", \"author\": \"user\", \"content\": \"Hello what can you do?\"},\n",
83+
" \"stream\": False\n",
84+
" }\n",
85+
")\n",
86+
"\n",
87+
"# # Extract and print just the text content from the response\n",
88+
"# # The response is expected to be a dict with a \"result\" key containing a list of message dicts\n",
89+
"if rpc_response and rpc_response.result:\n",
90+
"\n",
91+
" # We know that the result of the message/send when stream is set to False will be a list of TaskMessage objects\n",
92+
" task_message_list = cast(List[TaskMessage], rpc_response.result)\n",
93+
" for task_message in rpc_response.result:\n",
94+
" if isinstance(task_message, TaskMessage):\n",
95+
" content = task_message.content\n",
96+
" if isinstance(content, TextContent):\n",
97+
" text = content.content\n",
98+
" print(text)\n",
99+
" else:\n",
100+
" print(f\"Found non-text {type(task_message)} object in response.\")\n"
101+
]
102+
},
103+
{
104+
"cell_type": "code",
105+
"execution_count": 6,
106+
"id": "79688331",
107+
"metadata": {},
108+
"outputs": [
109+
{
110+
"name": "stdout",
111+
"output_type": "stream",
112+
"text": [
113+
"Hello! I've received your message. Here's a generic response, but in future tutorials we'll see how you can get me to intelligently respond to your message. This is what I heard you say: Hello what can you do?\n"
114+
]
115+
}
116+
],
117+
"source": [
118+
"# Test streaming response\n",
119+
"import json\n",
120+
"from agentex.types import AgentRpcResponse\n",
121+
"from agentex.types.agent_rpc_result import StreamTaskMessageDelta, StreamTaskMessageFull\n",
122+
"from agentex.types.text_delta import TextDelta\n",
123+
"from agentex.types.task_message_update import TaskMessageUpdate\n",
124+
"\n",
125+
"\n",
126+
"# The result object of message/send will be a TaskMessageUpdate which is a union of the following types:\n",
127+
"# - StreamTaskMessageStart: \n",
128+
"# - An indicator that a streaming message was started, doesn't contain any useful content\n",
129+
"# - StreamTaskMessageDelta: \n",
130+
"# - A delta of a streaming message, contains the text delta to aggregate\n",
131+
"# - StreamTaskMessageDone: \n",
132+
"# - An indicator that a streaming message was done, doesn't contain any useful content\n",
133+
"# - StreamTaskMessageFull: \n",
134+
"# - A non-streaming message, there is nothing to aggregate, since this contains the full message, not deltas\n",
135+
"\n",
136+
"# Whenn processing StreamTaskMessageDelta, if you are expecting more than TextDeltas, such as DataDelta, ToolRequestDelta, or ToolResponseDelta, you can process them as well\n",
137+
"# Whenn processing StreamTaskMessageFull, if you are expecting more than TextContent, such as DataContent, ToolRequestContent, or ToolResponseContent, you can process them as well\n",
138+
"\n",
139+
"with client.agents.with_streaming_response.rpc_by_name(\n",
140+
" agent_name=AGENT_NAME,\n",
141+
" method=\"message/send\",\n",
142+
" params={\n",
143+
" \"content\": {\"type\": \"text\", \"author\": \"user\", \"content\": \"Hello what can you do?\"},\n",
144+
" \"stream\": True\n",
145+
" }\n",
146+
") as response:\n",
147+
" for agent_rpc_response_str in response.iter_text():\n",
148+
" chunk_rpc_response = AgentRpcResponse.model_validate(json.loads(agent_rpc_response_str))\n",
149+
" # We know that the result of the message/send when stream is set to True will be a TaskMessageUpdate\n",
150+
" task_message_update = cast(TaskMessageUpdate, chunk_rpc_response.result)\n",
151+
"\n",
152+
" # Print oly the text deltas as they arrive or any full messages\n",
153+
" if isinstance(task_message_update, StreamTaskMessageDelta):\n",
154+
" delta = task_message_update.delta\n",
155+
" if isinstance(delta, TextDelta):\n",
156+
" print(delta.text_delta, end=\"\", flush=True)\n",
157+
" else:\n",
158+
" print(f\"Found non-text {type(task_message)} object in streaming message.\")\n",
159+
" elif isinstance(task_message_update, StreamTaskMessageFull):\n",
160+
" content = task_message_update.content\n",
161+
" if isinstance(content, TextContent):\n",
162+
" print(content.content)\n",
163+
" else:\n",
164+
" print(f\"Found non-text {type(task_message)} object in full message.\")\n"
165+
]
166+
},
167+
{
168+
"cell_type": "code",
169+
"execution_count": null,
170+
"id": "568673bf",
171+
"metadata": {},
172+
"outputs": [],
173+
"source": []
174+
}
175+
],
176+
"metadata": {
177+
"kernelspec": {
178+
"display_name": ".venv",
179+
"language": "python",
180+
"name": "python3"
181+
},
182+
"language_info": {
183+
"codemirror_mode": {
184+
"name": "ipython",
185+
"version": 3
186+
},
187+
"file_extension": ".py",
188+
"mimetype": "text/x-python",
189+
"name": "python",
190+
"nbconvert_exporter": "python",
191+
"pygments_lexer": "ipython3",
192+
"version": "3.12.9"
193+
}
194+
},
195+
"nbformat": 4,
196+
"nbformat_minor": 5
197+
}

0 commit comments

Comments
 (0)