grasp_agents 0.1.17__py3-none-any.whl → 0.2.0__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,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: grasp_agents
3
- Version: 0.1.17
3
+ Version: 0.2.0
4
4
  Summary: Grasp Agents Library
5
5
  License-File: LICENSE.md
6
6
  Requires-Python: <4,>=3.11.4
@@ -9,7 +9,7 @@ Requires-Dist: httpx<1,>=0.27.0
9
9
  Requires-Dist: openai<2,>=1.68.2
10
10
  Requires-Dist: pydantic>=2
11
11
  Requires-Dist: pyyaml>=6.0.2
12
- Requires-Dist: tenacity>=9.1.2
12
+ Requires-Dist: tenacity<9,>=8.3.0
13
13
  Requires-Dist: termcolor<3,>=2.4.0
14
14
  Requires-Dist: tqdm<5,>=4.66.2
15
15
  Description-Content-Type: text/markdown
@@ -17,7 +17,10 @@ Description-Content-Type: text/markdown
17
17
  # Grasp Agents
18
18
 
19
19
  <br/>
20
- <img src="./.assets/grasp.svg" alt="Grasp Agents" width="320" />
20
+ <picture>
21
+ <source srcset="./.assets/grasp-dark.svg" media="(prefers-color-scheme: dark)">
22
+ <img src="./.assets/grasp.svg" alt="Grasp Agents"/>
23
+ </picture>
21
24
  <br/>
22
25
  <br/>
23
26
 
@@ -34,14 +37,14 @@ Description-Content-Type: text/markdown
34
37
  ## Features
35
38
 
36
39
  - Clean formulation of agents as generic entities over:
37
- * I/O schemas
38
- * Agent state
39
- * Shared context
40
+ - I/O schemas
41
+ - Agent state
42
+ - Shared context
40
43
  - Transparent implementation of common agentic patterns:
41
44
  * Single-agent loops with an optional "ReAct mode" to enforce reasoning between the tool calls
42
45
  * Workflows (static communication topology), including loops
43
46
  * Agents-as-tools for task delegation
44
- * Freeform A2A communication via in-process Actor model
47
+ * Freeform A2A communication via the in-process actor model
45
48
  - Batch processing support outside of agentic loops
46
49
  - Simple logging and usage/cost tracking
47
50
 
@@ -54,7 +57,7 @@ Description-Content-Type: text/markdown
54
57
  - `prompt_builder.py`: Tools for constructing prompts.
55
58
  - `workflow/`: Modules for defining and managing agent workflows.
56
59
  - `cloud_llm.py`, `llm.py`: LLM integration and base LLM functionalities.
57
- - `openai/`: Modules specific to OpenAI API integration.
60
+ - `openai/`: Modules specific to OpenAI API integration.
58
61
  - `memory.py`: Memory management for agents (currently only message history).
59
62
  - `run_context.py`: Context management for agent runs.
60
63
  - `usage_tracker.py`: Tracking of API usage and costs.
@@ -107,18 +110,20 @@ GOOGLE_AI_STUDIO_API_KEY=your_google_ai_studio_api_key
107
110
  Create a script, e.g., `problem_recommender.py`:
108
111
 
109
112
  ```python
113
+ import asyncio
110
114
  import re
111
- from typing import Any
112
115
  from pathlib import Path
113
- from pydantic import BaseModel, Field
116
+ from typing import Any
117
+
114
118
  from dotenv import load_dotenv
115
- from grasp_agents.typing.tool import BaseTool
116
- from grasp_agents.typing.io import AgentPayload
117
- from grasp_agents.run_context import RunContextWrapper
118
- from grasp_agents.openai.openai_llm import OpenAILLM, OpenAILLMSettings
119
- from grasp_agents.llm_agent import LLMAgent
119
+ from pydantic import BaseModel, Field
120
+
120
121
  from grasp_agents.grasp_logging import setup_logging
122
+ from grasp_agents.llm_agent import LLMAgent
123
+ from grasp_agents.openai.openai_llm import OpenAILLM, OpenAILLMSettings
124
+ from grasp_agents.run_context import RunContextWrapper
121
125
  from grasp_agents.typing.message import Conversation
126
+ from grasp_agents.typing.tool import BaseTool
122
127
 
123
128
  load_dotenv()
124
129
 
@@ -130,8 +135,8 @@ setup_logging(
130
135
  )
131
136
 
132
137
  sys_prompt_react = """
133
- Your task is to suggest an exciting stats problem to a student.
134
- Ask the student about their education, interests, and preferences, then suggest a problem tailored to them.
138
+ Your task is to suggest an exciting stats problem to a student.
139
+ Ask the student about their education, interests, and preferences, then suggest a problem tailored to them.
135
140
 
136
141
  # Instructions
137
142
  * Ask questions one by one.
@@ -143,14 +148,13 @@ Ask the student about their education, interests, and preferences, then suggest
143
148
  class TeacherQuestion(BaseModel):
144
149
  question: str = Field(..., description="The question to ask the student.")
145
150
 
151
+
146
152
  StudentReply = str
147
153
 
148
154
 
149
155
  class AskStudentTool(BaseTool[TeacherQuestion, StudentReply, Any]):
150
156
  name: str = "ask_student_tool"
151
157
  description: str = "Ask the student a question and get their reply."
152
- in_schema: type[TeacherQuestion] = TeacherQuestion
153
- out_schema: type[StudentReply] = StudentReply
154
158
 
155
159
  async def run(
156
160
  self, inp: TeacherQuestion, ctx: RunContextWrapper[Any] | None = None
@@ -158,11 +162,10 @@ class AskStudentTool(BaseTool[TeacherQuestion, StudentReply, Any]):
158
162
  return input(inp.question)
159
163
 
160
164
 
161
- class FinalResponse(AgentPayload):
162
- problem: str
165
+ Problem = str
163
166
 
164
167
 
165
- teacher = LLMAgent[Any, FinalResponse, None](
168
+ teacher = LLMAgent[Any, Problem, None](
166
169
  agent_id="teacher",
167
170
  llm=OpenAILLM(
168
171
  model_name="gpt-4.1",
@@ -173,30 +176,31 @@ teacher = LLMAgent[Any, FinalResponse, None](
173
176
  max_turns=20,
174
177
  react_mode=True,
175
178
  sys_prompt=sys_prompt_react,
176
- out_schema=FinalResponse,
177
179
  set_state_strategy="reset",
178
180
  )
179
181
 
180
182
 
181
- @teacher.tool_call_loop_exit_handler
182
- def exit_tool_call_loop(conversation: Conversation, ctx, **kwargs) -> None:
183
- message_text = conversation[-1].content
184
-
185
- return re.search(r"<PROBLEM>", message_text)
183
+ @teacher.exit_tool_call_loop_handler
184
+ def exit_tool_call_loop(
185
+ conversation: Conversation, ctx: RunContextWrapper[Any] | None, **kwargs: Any
186
+ ) -> bool:
187
+ return r"<PROBLEM>" in str(conversation[-1].content)
186
188
 
187
189
 
188
190
  @teacher.parse_output_handler
189
- def parse_output(conversation: Conversation, ctx, **kwargs) -> FinalResponse:
190
- message_text = conversation[-1].content
191
- matches = re.findall(r"<PROBLEM>(.*?)</PROBLEM>", message_text, re.DOTALL)
191
+ def parse_output(
192
+ conversation: Conversation, ctx: RunContextWrapper[Any] | None, **kwargs: Any
193
+ ) -> Problem:
194
+ message = str(conversation[-1].content)
195
+ matches = re.findall(r"<PROBLEM>(.*?)</PROBLEM>", message, re.DOTALL)
192
196
 
193
- return FinalResponse(problem=matches[0])
197
+ return matches[0]
194
198
 
195
199
 
196
200
  async def main():
197
- ctx = RunContextWrapper(print_messages=True)
201
+ ctx = RunContextWrapper[None](print_messages=True)
198
202
  out = await teacher.run(ctx=ctx)
199
- print(out.payloads[0].problem)
203
+ print(out.payloads[0])
200
204
  print(ctx.usage_tracker.total_usage)
201
205
 
202
206
 
@@ -0,0 +1,45 @@
1
+ grasp_agents/agent_message.py,sha256=eJV5n44t8EIE6M3jl48Ld7pmaW9dDhBX_FWm_u9yGWE,877
2
+ grasp_agents/agent_message_pool.py,sha256=OKTXNEo9LAJTQJkzxmJ3TQgWw7WJKOzrKCJjeHpln6o,3158
3
+ grasp_agents/base_agent.py,sha256=BOLYxS_cSisOR4qupUYIVn2FW15svit3jbNNfjw_cT8,1347
4
+ grasp_agents/cloud_llm.py,sha256=X9o9x9TsX1zCBmzO-swEcTWhReQ8wHpFpFj3-kOT_-M,13116
5
+ grasp_agents/comm_agent.py,sha256=e2IsatGLxdDkSZpPxQm6s1ha6w0Z9XAzRU1L4qb9wNY,7280
6
+ grasp_agents/costs_dict.yaml,sha256=EW6XxRXLZobMwQEEiUNYALbDzfbZFb2zEVCaTSAqYjw,2334
7
+ grasp_agents/generics_utils.py,sha256=kw4Odte6Nvl4c9U7-mKPgXCavWZXo009zYDHAA0BR3g,6234
8
+ grasp_agents/grasp_logging.py,sha256=H1GYhXdQvVkmauFDZ-KDwvVmPQHZUUm9sRqX_ObK2xI,1111
9
+ grasp_agents/http_client.py,sha256=KZva2MjJjuI5ohUeU8RdTAImUnQYaqBrV2jDH8smbJw,738
10
+ grasp_agents/llm.py,sha256=n67lXbB8spr_i3Xz0Plw7oeykfjQmVHHkSiveqBB5Lw,3150
11
+ grasp_agents/llm_agent.py,sha256=V8aStNrrBFMEhqBpuq-YxpTPMPJAsvYBXzBV_uxg0qY,13468
12
+ grasp_agents/llm_agent_state.py,sha256=Bt470miFHTFnxdIXUjd7jha6FWDf0hUuMI8n_G6cZI8,2439
13
+ grasp_agents/memory.py,sha256=X1YtVX8XxP5KnGPMW8BqjID8QK4hTG2obxoyhnnZ4pU,5575
14
+ grasp_agents/printer.py,sha256=Jk6OJExio53gbKBod5Dd8Y3CWYrVb4K5q4UJ8i9cQvo,5024
15
+ grasp_agents/prompt_builder.py,sha256=G1ZX0sCnA6_-rBi44ZtkiNU6h7Jpvu-5dTM4ok2ax70,8043
16
+ grasp_agents/run_context.py,sha256=M4w_HXl5aiz-18CDlfNCRNZm3m5UIQMrjKkhurFTtkY,2229
17
+ grasp_agents/tool_orchestrator.py,sha256=BCzeLTJkXOFXjKTRs75fRs1vJVvavbTEXzvHFEvwCM4,6167
18
+ grasp_agents/usage_tracker.py,sha256=5YuN6hpg6HASdg-hOylgWzhCiORmDMnZuQtbISfhm_4,3378
19
+ grasp_agents/utils.py,sha256=NzMg11w7akRyMOYjS6hHTE2XZ7DKeuM5BD1SRfFFsNk,5350
20
+ grasp_agents/openai/__init__.py,sha256=qN8HMAatSJKOsA6v-JwakMYguwkswCVHqrmK1gFy9wI,3096
21
+ grasp_agents/openai/completion_converters.py,sha256=lX9h1kaGAo5ttsl-4V7l4x8IpjxJaJJtyU2cKu3-EOc,1871
22
+ grasp_agents/openai/content_converters.py,sha256=6GI0D7xJalzsiawAJOyCUzTJTo0NQdpv87YKmfN0LYQ,2631
23
+ grasp_agents/openai/converters.py,sha256=DBXBxow9oRG6pc8inpZBLiuUqHzVfpscmHFpN9bAdvc,5276
24
+ grasp_agents/openai/message_converters.py,sha256=KjF6FbXzwlWdM-1YT3cswUV-74sjiwOhLFPMY4sJ5Xk,4593
25
+ grasp_agents/openai/openai_llm.py,sha256=dscGlVhH4v1yAw4NRPgJdww9toOoMRpIqA6HD4IGWOs,6132
26
+ grasp_agents/openai/tool_converters.py,sha256=KhWRETkjhjocISUo_HBZ8QfBiyTOoC5WurPNAR4BYxc,1027
27
+ grasp_agents/rate_limiting/__init__.py,sha256=KRgtF_E7R3YfA2cpYcFcZ7wycV0pWVJ0xRQC7YhiIEQ,158
28
+ grasp_agents/rate_limiting/rate_limiter_chunked.py,sha256=BPgkUXvhmZhTpZs2T6uujNFuxH_kYHiISuf6_-eNhUc,5544
29
+ grasp_agents/rate_limiting/types.py,sha256=PbnNhEAcYedQdIpPJWud8HUVcxa_xZS2RDZu4c5jr40,1003
30
+ grasp_agents/rate_limiting/utils.py,sha256=oEDWDNHYMUdxOOG49PlAJochkZq8nnVBCo6JxPc1iSo,2007
31
+ grasp_agents/typing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
+ grasp_agents/typing/completion.py,sha256=_KDLx3Gtz7o-pEZrvAFgCZwDmkr2oQkxrL-2LSXHHsw,657
33
+ grasp_agents/typing/content.py,sha256=13nLNZqZgtpo9sM0vCRQmZ4bQjjZqUSElMQOwjL7bO8,3651
34
+ grasp_agents/typing/converters.py,sha256=yORIljRsVoKz7oj38pHLD6luIelM1RcYL_PqG_D4nWM,3086
35
+ grasp_agents/typing/io.py,sha256=aDT8tpZYc2R2jOa6QU0xO_HJYEBqCkeL1flHDugrsOg,541
36
+ grasp_agents/typing/message.py,sha256=oCpqD_CV2Da-M-l-e5liFJSwK8267fxfcU68LIc7C1E,3801
37
+ grasp_agents/typing/tool.py,sha256=l6TlWGpeUiJuXWUa0g1Xx7lw7jxZOpZ0bK63Ixt9h5A,2240
38
+ grasp_agents/workflow/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
+ grasp_agents/workflow/looped_agent.py,sha256=8NVy6dAwEs7f6JgYHZUI1h-N8SabpND4n-3rSy5mh70,3945
40
+ grasp_agents/workflow/sequential_agent.py,sha256=Ral6Bvsl5-NdO-uKMGiWuz5EE9rNcYb1lXhY8CcQw4w,2054
41
+ grasp_agents/workflow/workflow_agent.py,sha256=LadvEJTsV6YEGRb_eaYgu5r7k1aa8N-2FHXMYJpbBVU,2460
42
+ grasp_agents-0.2.0.dist-info/METADATA,sha256=TfFjGFaXtrnwSbjy-Hr2m9TR0ryW4CZN75QJJlFZ3ds,6889
43
+ grasp_agents-0.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
44
+ grasp_agents-0.2.0.dist-info/licenses/LICENSE.md,sha256=Kfeo0gdlLS6tLQiWwO9UWhjp9-f93a5kShSiBp2FG-c,1201
45
+ grasp_agents-0.2.0.dist-info/RECORD,,
@@ -1,44 +0,0 @@
1
- grasp_agents/agent_message.py,sha256=Z-czIHNSe7eAo5r6q2Zu10HFpUjQjVbayyglGyyj4Lw,911
2
- grasp_agents/agent_message_pool.py,sha256=4O4xz-aZ_I5m3iLAUiMAQcVn5AGRP4daUM8XME03Xsw,3250
3
- grasp_agents/base_agent.py,sha256=4mNMyWdt9MTzg64JhrVjcU_FSYDj0ED_AKpRZXCRVb4,1870
4
- grasp_agents/cloud_llm.py,sha256=JJmIUu8SOJ4TElQ4B19mPgXJ1SiapZdPFFhA2YVRKRw,13015
5
- grasp_agents/comm_agent.py,sha256=ukkT0zXgE8-yt63fyi3MQ_3Q0QjwIDHKz4MbHt9FBxw,7323
6
- grasp_agents/costs_dict.yaml,sha256=EW6XxRXLZobMwQEEiUNYALbDzfbZFb2zEVCaTSAqYjw,2334
7
- grasp_agents/grasp_logging.py,sha256=H1GYhXdQvVkmauFDZ-KDwvVmPQHZUUm9sRqX_ObK2xI,1111
8
- grasp_agents/http_client.py,sha256=KZva2MjJjuI5ohUeU8RdTAImUnQYaqBrV2jDH8smbJw,738
9
- grasp_agents/llm.py,sha256=RZY25UNJEdPUmqOHifUrrQTgfoDCAVtZN9WQvvxnLC4,3004
10
- grasp_agents/llm_agent.py,sha256=_D16rA8LDhALZKYYuWxB-E75g3uBgzM04EcJyuRMKZA,12619
11
- grasp_agents/llm_agent_state.py,sha256=91K1-8Uodbe-t_I6nu0xBzHfQjssZYCHjMuDbu5aCr0,2327
12
- grasp_agents/memory.py,sha256=X1YtVX8XxP5KnGPMW8BqjID8QK4hTG2obxoyhnnZ4pU,5575
13
- grasp_agents/printer.py,sha256=Jk6OJExio53gbKBod5Dd8Y3CWYrVb4K5q4UJ8i9cQvo,5024
14
- grasp_agents/prompt_builder.py,sha256=rYVIY4adJwBitjrTYvpEh5x8C7cLbIiXxT1F-vQuvEM,7393
15
- grasp_agents/run_context.py,sha256=hyETO3-p0azPFws75kX6rrUDLf58Ar6jmyt6TQ5Po78,2589
16
- grasp_agents/tool_orchestrator.py,sha256=6VX8FGYeUHiSt9GpUjOga7KGP55Kzs1jEiNcOZysIAo,5501
17
- grasp_agents/usage_tracker.py,sha256=5YuN6hpg6HASdg-hOylgWzhCiORmDMnZuQtbISfhm_4,3378
18
- grasp_agents/utils.py,sha256=-OdCs27FKek8owGbwmAVWwLXDgEzoTu-B5_EwRLEsz4,5869
19
- grasp_agents/openai/__init__.py,sha256=qN8HMAatSJKOsA6v-JwakMYguwkswCVHqrmK1gFy9wI,3096
20
- grasp_agents/openai/completion_converters.py,sha256=lX9h1kaGAo5ttsl-4V7l4x8IpjxJaJJtyU2cKu3-EOc,1871
21
- grasp_agents/openai/content_converters.py,sha256=6GI0D7xJalzsiawAJOyCUzTJTo0NQdpv87YKmfN0LYQ,2631
22
- grasp_agents/openai/converters.py,sha256=DBXBxow9oRG6pc8inpZBLiuUqHzVfpscmHFpN9bAdvc,5276
23
- grasp_agents/openai/message_converters.py,sha256=KjF6FbXzwlWdM-1YT3cswUV-74sjiwOhLFPMY4sJ5Xk,4593
24
- grasp_agents/openai/openai_llm.py,sha256=dscGlVhH4v1yAw4NRPgJdww9toOoMRpIqA6HD4IGWOs,6132
25
- grasp_agents/openai/tool_converters.py,sha256=KhWRETkjhjocISUo_HBZ8QfBiyTOoC5WurPNAR4BYxc,1027
26
- grasp_agents/rate_limiting/__init__.py,sha256=KRgtF_E7R3YfA2cpYcFcZ7wycV0pWVJ0xRQC7YhiIEQ,158
27
- grasp_agents/rate_limiting/rate_limiter_chunked.py,sha256=jp6bqWGq2qYAxbmyU_bAGeBXM_nEmSrR6VabDutcTA0,5800
28
- grasp_agents/rate_limiting/types.py,sha256=JbLYJC-gmzcHH_4-YNTz9IcIwVpcpDyDGvljxNznf5k,1389
29
- grasp_agents/rate_limiting/utils.py,sha256=yrqboDWWqeekDcs0xaeOPOvelhgAlywDpQpscpPqlhg,1995
30
- grasp_agents/typing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
- grasp_agents/typing/completion.py,sha256=_KDLx3Gtz7o-pEZrvAFgCZwDmkr2oQkxrL-2LSXHHsw,657
32
- grasp_agents/typing/content.py,sha256=13nLNZqZgtpo9sM0vCRQmZ4bQjjZqUSElMQOwjL7bO8,3651
33
- grasp_agents/typing/converters.py,sha256=EbGur_Ngx-wINfyOEHa7JqmKnMAxZ5vJjhAPoqBf_AM,3048
34
- grasp_agents/typing/io.py,sha256=M294tNROa9gJ_I38c9pLekEbUK2p3qirYdE_QGpuw1c,624
35
- grasp_agents/typing/message.py,sha256=oCpqD_CV2Da-M-l-e5liFJSwK8267fxfcU68LIc7C1E,3801
36
- grasp_agents/typing/tool.py,sha256=t40vr3ljQY_Qx0f0KZIc151bYlHUF7Bf7JfOkiJOi2c,1657
37
- grasp_agents/workflow/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
- grasp_agents/workflow/looped_agent.py,sha256=YBOgOIvy3_NwKvEoGgzQJ2fY9SNG66MQk6obSBGWvCc,3896
39
- grasp_agents/workflow/sequential_agent.py,sha256=yDt2nA-b1leVByD8jsKrWD6bHe0o9z33jrOJGOLwbyk,2004
40
- grasp_agents/workflow/workflow_agent.py,sha256=9U94IQ39Vb1W_5u8aoqHb65ikdarEhEJkexDz8xwHD4,2294
41
- grasp_agents-0.1.17.dist-info/METADATA,sha256=YG_CGwTAOAQFAOA_Aqi6pqwF_ODYtzY_nQEgf2IRMFM,7001
42
- grasp_agents-0.1.17.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
43
- grasp_agents-0.1.17.dist-info/licenses/LICENSE.md,sha256=Kfeo0gdlLS6tLQiWwO9UWhjp9-f93a5kShSiBp2FG-c,1201
44
- grasp_agents-0.1.17.dist-info/RECORD,,