grasp_agents_legacy 0.6.50__tar.gz

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.
Files changed (78) hide show
  1. grasp_agents_legacy-0.6.50/.gitignore +177 -0
  2. grasp_agents_legacy-0.6.50/LICENSE.md +1 -0
  3. grasp_agents_legacy-0.6.50/PKG-INFO +189 -0
  4. grasp_agents_legacy-0.6.50/README.md +163 -0
  5. grasp_agents_legacy-0.6.50/pyproject.toml +59 -0
  6. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/__init__.py +44 -0
  7. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/cloud_llm.py +251 -0
  8. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/costs_dict.yaml +130 -0
  9. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/errors.py +156 -0
  10. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/event_bus.py +161 -0
  11. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/generics_utils.py +168 -0
  12. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/grasp_logging.py +36 -0
  13. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/litellm/__init__.py +106 -0
  14. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/litellm/completion_chunk_converters.py +67 -0
  15. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/litellm/completion_converters.py +67 -0
  16. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/litellm/converters.py +150 -0
  17. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/litellm/lite_llm.py +304 -0
  18. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/litellm/message_converters.py +66 -0
  19. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/llm.py +392 -0
  20. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/llm_agent.py +532 -0
  21. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/llm_agent_memory.py +41 -0
  22. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/llm_policy_executor.py +663 -0
  23. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/memory.py +51 -0
  24. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/openai/__init__.py +16 -0
  25. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/openai/completions/__init__.py +84 -0
  26. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/openai/completions/chunk_converters.py +78 -0
  27. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/openai/completions/completion_converters.py +76 -0
  28. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/openai/completions/content_converters.py +77 -0
  29. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/openai/completions/converters.py +147 -0
  30. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/openai/completions/message_converters.py +159 -0
  31. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/openai/completions/openai_llm_completions.py +284 -0
  32. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/openai/completions/tool_converters.py +42 -0
  33. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/openai/responses/__init__.py +3 -0
  34. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/openai/responses/chunk_converters.py +123 -0
  35. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/openai/responses/completion_converters.py +41 -0
  36. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/openai/responses/completion_item_converters.py +33 -0
  37. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/openai/responses/content_converters.py +73 -0
  38. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/openai/responses/converters.py +157 -0
  39. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/openai/responses/message_converters.py +205 -0
  40. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/openai/responses/openai_responses_api.py +209 -0
  41. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/openai/responses/tool_converters.py +32 -0
  42. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/packet.py +107 -0
  43. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/printer.py +359 -0
  44. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/processors/base_processor.py +210 -0
  45. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/processors/parallel_processor.py +148 -0
  46. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/processors/processor.py +281 -0
  47. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/prompt_builder.py +176 -0
  48. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/rate_limiting/__init__.py +3 -0
  49. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/rate_limiting/rate_limiter.py +89 -0
  50. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/rate_limiting/types.py +10 -0
  51. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/rate_limiting/utils.py +51 -0
  52. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/run_context.py +24 -0
  53. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/runner.py +182 -0
  54. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/telemetry/exporters.py +91 -0
  55. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/telemetry/phoenix.py +67 -0
  56. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/telemetry/traceloop.py +32 -0
  57. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/tracing_decorators/__init__.py +63 -0
  58. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/tracing_decorators/base.py +442 -0
  59. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/typing/__init__.py +0 -0
  60. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/typing/completion.py +77 -0
  61. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/typing/completion_chunk.py +431 -0
  62. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/typing/completion_item.py +22 -0
  63. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/typing/content.py +125 -0
  64. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/typing/converters.py +116 -0
  65. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/typing/events.py +387 -0
  66. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/typing/io.py +9 -0
  67. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/typing/message.py +139 -0
  68. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/typing/tool.py +107 -0
  69. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/usage_tracker.py +102 -0
  70. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/utils/__init__.py +0 -0
  71. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/utils/callbacks.py +26 -0
  72. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/utils/io.py +28 -0
  73. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/utils/streaming.py +104 -0
  74. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/utils/validation.py +139 -0
  75. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/workflow/__init__.py +0 -0
  76. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/workflow/looped_workflow.py +182 -0
  77. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/workflow/sequential_workflow.py +104 -0
  78. grasp_agents_legacy-0.6.50/src/grasp_agents_legacy/workflow/workflow_processor.py +91 -0
@@ -0,0 +1,177 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py,cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ #uv.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ #poetry.lock
109
+
110
+ # pdm
111
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
112
+ #pdm.lock
113
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
114
+ # in version control.
115
+ # https://pdm.fming.dev/latest/usage/project/#working-with-version-control
116
+ .pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
121
+ __pypackages__/
122
+
123
+ # Celery stuff
124
+ celerybeat-schedule
125
+ celerybeat.pid
126
+
127
+ # SageMath parsed files
128
+ *.sage.py
129
+
130
+ # Environments
131
+ .env
132
+ .venv
133
+ env/
134
+ venv/
135
+ ENV/
136
+ env.bak/
137
+ venv.bak/
138
+
139
+ # Spyder project settings
140
+ .spyderproject
141
+ .spyproject
142
+
143
+ # Rope project settings
144
+ .ropeproject
145
+
146
+ # mkdocs documentation
147
+ /site
148
+
149
+ # mypy
150
+ .mypy_cache/
151
+ .dmypy.json
152
+ dmypy.json
153
+
154
+ # Pyre type checker
155
+ .pyre/
156
+
157
+ # pytype static type analyzer
158
+ .pytype/
159
+
160
+ # Cython debug symbols
161
+ cython_debug/
162
+
163
+ # PyCharm
164
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
165
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
166
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
167
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
168
+ #.idea/
169
+
170
+ # Ruff stuff:
171
+ .ruff_cache/
172
+
173
+ # PyPI configuration file
174
+ .pypirc
175
+
176
+ # MAC OS files
177
+ **/.DS_Store
@@ -0,0 +1 @@
1
+ Grasp Agents itself is [MIT](https://mit-license.org/)-licensed.
@@ -0,0 +1,189 @@
1
+ Metadata-Version: 2.4
2
+ Name: grasp_agents_legacy
3
+ Version: 0.6.50
4
+ Summary: Grasp Agents Library
5
+ License-File: LICENSE.md
6
+ Requires-Python: <4,>=3.11.4
7
+ Requires-Dist: google-genai>=1.45.0
8
+ Requires-Dist: httpx<1,>=0.27.0
9
+ Requires-Dist: litellm==1.83.10
10
+ Requires-Dist: numpy<2
11
+ Requires-Dist: openai<3,>=1.68.2
12
+ Requires-Dist: opentelemetry-sdk>=1.37.0
13
+ Requires-Dist: pydantic>=2
14
+ Requires-Dist: python-dotenv>=1.0
15
+ Requires-Dist: pyyaml>=6.0.2
16
+ Requires-Dist: tenacity<9,>=8.3.0
17
+ Requires-Dist: termcolor<3,>=2.4.0
18
+ Requires-Dist: tqdm<5,>=4.66.2
19
+ Requires-Dist: traceloop-sdk>=0.47.2
20
+ Provides-Extra: observability
21
+ Requires-Dist: arize-phoenix-otel>=0.13.1; extra == 'observability'
22
+ Requires-Dist: openinference-instrumentation-litellm>=0.1.25; extra == 'observability'
23
+ Requires-Dist: openinference-instrumentation-openai>=0.1.32; extra == 'observability'
24
+ Requires-Dist: openinference-instrumentation-openllmetry>=0.1.2; extra == 'observability'
25
+ Description-Content-Type: text/markdown
26
+
27
+ # Grasp Agents
28
+
29
+ <br/>
30
+ <picture>
31
+ <source srcset="https://raw.githubusercontent.com/grasp-technologies/grasp-agents/master/.assets/grasp-dark.svg" media="(prefers-color-scheme: dark)">
32
+ <img src="https://raw.githubusercontent.com/grasp-technologies/grasp-agents/master/.assets/grasp.svg" alt="Grasp Agents"/>
33
+ </picture>
34
+ <br/>
35
+ <br/>
36
+
37
+ [![PyPI version](https://badge.fury.io/py/grasp_agents.svg)](https://badge.fury.io/py/grasp-agents)
38
+ [![License: MIT](https://img.shields.io/badge/license-MIT-yellow?style=flat-square)](https://mit-license.org/)
39
+ [![PyPI downloads](https://img.shields.io/pypi/dm/grasp-agents?style=flat-square)](https://pypi.org/project/grasp-agents/)
40
+ [![GitHub Stars](https://img.shields.io/github/stars/grasp-technologies/grasp-agents?style=social)](https://github.com/grasp-technologies/grasp-agents/stargazers)
41
+ [![GitHub Forks](https://img.shields.io/github/forks/grasp-technologies/grasp-agents?style=social)](https://github.com/grasp-technologies/grasp-agents/network/members)
42
+
43
+ ## Overview
44
+
45
+ **Grasp Agents** is a modular Python framework for building agentic AI pipelines and applications. It is meant to be minimalistic but functional, allowing for rapid experimentation while keeping full and granular low-level control over prompting, LLM handling, tool call loops, and inter-agent communication by avoiding excessive higher-level abstractions.
46
+
47
+ ## Features
48
+
49
+ - Clean formulation of agents as generic entities over I/O schemas and shared context.
50
+ - Transparent implementation of common agentic patterns:
51
+ - Single-agent loops
52
+ - Workflows (static communication topology), including loops
53
+ - Agents-as-tools for task delegation
54
+ - Freeform A2A communication via the in-process actor model
55
+ - Built-in parallel processing with flexible retries and rate limiting.
56
+ - Support for all popular API providers via LiteLLM.
57
+ - Granular event streaming with separate events for LLM responses, thinking, and tool calls.
58
+ - Callbacks via decorators or subclassing for straightforward customisation of agentic loops and context management.
59
+
60
+ ## Project Structure
61
+
62
+ - `processors/`, `llm_agent.py`: Core processor and agent class implementations.
63
+ - `event_bus.py`, `runner.py`: Communication management and orchestration.
64
+ - `llm_policy_executor.py`: LLM actions and tool call loops.
65
+ - `prompt_builder.py`: Tools for constructing prompts.
66
+ - `workflow/`: Modules for defining and managing static agent workflows.
67
+ - `llm.py`, `cloud_llm.py`: LLM integration and base LLM functionalities.
68
+ - `openai/`: Modules specific to OpenAI API integration.
69
+ - `litellm/`: Modules specific to LiteLLM integration.
70
+ - `memory.py`, `llm_agent_memory.py`: Memory management.
71
+ - `run_context.py`: Shared run context management.
72
+
73
+ ## Usage
74
+
75
+ ### Installation
76
+
77
+ Assuming your project manages dependencies through [uv](https://docs.astral.sh/uv/).
78
+
79
+ ```bash
80
+ uv add grasp_agents
81
+ uv sync
82
+ ```
83
+
84
+ You can of course also install using other managers like poetry or simply pip.
85
+
86
+ We recommend you use [dotenv](https://pypi.org/project/python-dotenv/) to automatically set enviroment variables from a `.env` file containting the necessary API keys, e.g.,
87
+
88
+ ```
89
+ ANTHROPIC_API_KEY=your_anthropic_api_key
90
+ ```
91
+
92
+ ### Try it out
93
+
94
+ #### Jupyter Notebook Example
95
+ [Notebook Link](https://github.com/grasp-technologies/grasp-agents/blob/master/src/grasp_agents/examples/notebooks/agents_demo.ipynb)
96
+
97
+ #### A Grasp-Agents Powered Web App
98
+ [https://grasp.study/](https://grasp.study/)
99
+
100
+ #### Script Example
101
+
102
+ Create a script, e.g., `problem_recommender.py`:
103
+
104
+ ```python
105
+ import asyncio
106
+ from typing import Any
107
+
108
+ from dotenv import load_dotenv
109
+ from pydantic import BaseModel
110
+
111
+ from grasp_agents import BaseTool, LLMAgent, RunContext
112
+ from grasp_agents.litellm import LiteLLM, LiteLLMSettings
113
+ from grasp_agents.printer import print_event_stream
114
+ from grasp_agents.typing.events import ProcPacketOutEvent
115
+
116
+ load_dotenv()
117
+
118
+ sys_prompt = """
119
+ Your task is to suggest an exciting stats problem to the student.
120
+ You should first ask the student about their education, interests, and preferences, then suggest a problem tailored specifically to them.
121
+
122
+ # Instructions
123
+ * Use the provided tool to ask questions.
124
+ * Ask questions one by one.
125
+ * The problem must have all the necessary data.
126
+ * Use the final answer tool to provide the problem.
127
+ """
128
+
129
+
130
+ class TeacherQuestion(BaseModel):
131
+ question: str
132
+
133
+
134
+ StudentReply = str
135
+
136
+
137
+ ask_student_tool_description = """
138
+ "Ask the student a question and get their reply."
139
+
140
+ Args:
141
+ question: str
142
+ The question to ask the student.
143
+ Returns:
144
+ reply: str
145
+ The student's reply to the question.
146
+ """
147
+
148
+
149
+ class AskStudentTool(BaseTool[TeacherQuestion, StudentReply, None]):
150
+ name: str = "ask_student"
151
+ description: str = ask_student_tool_description
152
+
153
+ async def run(self, inp: TeacherQuestion, **kwargs: Any) -> StudentReply:
154
+ return input(inp.question)
155
+
156
+
157
+ class Problem(BaseModel):
158
+ problem: str
159
+
160
+
161
+ teacher = LLMAgent[None, Problem, None](
162
+ name="teacher",
163
+ llm=LiteLLM(
164
+ model_name="claude-sonnet-4-5",
165
+ llm_settings=LiteLLMSettings(reasoning_effort="low"),
166
+ ),
167
+ tools=[AskStudentTool()],
168
+ final_answer_as_tool_call=True,
169
+ sys_prompt=sys_prompt,
170
+ stream_llm_responses=True,
171
+ )
172
+
173
+ async def main():
174
+ ctx = RunContext[None]()
175
+ async for event in print_event_stream(teacher.run_stream("start", ctx=ctx)):
176
+ if isinstance(event, ProcPacketOutEvent):
177
+ result = event.data.payloads[0]
178
+ print(f"\n<Suggested Problem>:\n\n{result.problem}\n")
179
+
180
+ asyncio.run(main())
181
+ ```
182
+
183
+ Run your script:
184
+
185
+ ```bash
186
+ uv run problem_recommender.py
187
+ ```
188
+
189
+ You can find more examples in [src/grasp_agents/examples/notebooks/agents_demo.ipynb](https://github.com/grasp-technologies/grasp-agents/tree/master/src/grasp_agents/examples/notebooks/agents_demo.ipynb).
@@ -0,0 +1,163 @@
1
+ # Grasp Agents
2
+
3
+ <br/>
4
+ <picture>
5
+ <source srcset="https://raw.githubusercontent.com/grasp-technologies/grasp-agents/master/.assets/grasp-dark.svg" media="(prefers-color-scheme: dark)">
6
+ <img src="https://raw.githubusercontent.com/grasp-technologies/grasp-agents/master/.assets/grasp.svg" alt="Grasp Agents"/>
7
+ </picture>
8
+ <br/>
9
+ <br/>
10
+
11
+ [![PyPI version](https://badge.fury.io/py/grasp_agents.svg)](https://badge.fury.io/py/grasp-agents)
12
+ [![License: MIT](https://img.shields.io/badge/license-MIT-yellow?style=flat-square)](https://mit-license.org/)
13
+ [![PyPI downloads](https://img.shields.io/pypi/dm/grasp-agents?style=flat-square)](https://pypi.org/project/grasp-agents/)
14
+ [![GitHub Stars](https://img.shields.io/github/stars/grasp-technologies/grasp-agents?style=social)](https://github.com/grasp-technologies/grasp-agents/stargazers)
15
+ [![GitHub Forks](https://img.shields.io/github/forks/grasp-technologies/grasp-agents?style=social)](https://github.com/grasp-technologies/grasp-agents/network/members)
16
+
17
+ ## Overview
18
+
19
+ **Grasp Agents** is a modular Python framework for building agentic AI pipelines and applications. It is meant to be minimalistic but functional, allowing for rapid experimentation while keeping full and granular low-level control over prompting, LLM handling, tool call loops, and inter-agent communication by avoiding excessive higher-level abstractions.
20
+
21
+ ## Features
22
+
23
+ - Clean formulation of agents as generic entities over I/O schemas and shared context.
24
+ - Transparent implementation of common agentic patterns:
25
+ - Single-agent loops
26
+ - Workflows (static communication topology), including loops
27
+ - Agents-as-tools for task delegation
28
+ - Freeform A2A communication via the in-process actor model
29
+ - Built-in parallel processing with flexible retries and rate limiting.
30
+ - Support for all popular API providers via LiteLLM.
31
+ - Granular event streaming with separate events for LLM responses, thinking, and tool calls.
32
+ - Callbacks via decorators or subclassing for straightforward customisation of agentic loops and context management.
33
+
34
+ ## Project Structure
35
+
36
+ - `processors/`, `llm_agent.py`: Core processor and agent class implementations.
37
+ - `event_bus.py`, `runner.py`: Communication management and orchestration.
38
+ - `llm_policy_executor.py`: LLM actions and tool call loops.
39
+ - `prompt_builder.py`: Tools for constructing prompts.
40
+ - `workflow/`: Modules for defining and managing static agent workflows.
41
+ - `llm.py`, `cloud_llm.py`: LLM integration and base LLM functionalities.
42
+ - `openai/`: Modules specific to OpenAI API integration.
43
+ - `litellm/`: Modules specific to LiteLLM integration.
44
+ - `memory.py`, `llm_agent_memory.py`: Memory management.
45
+ - `run_context.py`: Shared run context management.
46
+
47
+ ## Usage
48
+
49
+ ### Installation
50
+
51
+ Assuming your project manages dependencies through [uv](https://docs.astral.sh/uv/).
52
+
53
+ ```bash
54
+ uv add grasp_agents
55
+ uv sync
56
+ ```
57
+
58
+ You can of course also install using other managers like poetry or simply pip.
59
+
60
+ We recommend you use [dotenv](https://pypi.org/project/python-dotenv/) to automatically set enviroment variables from a `.env` file containting the necessary API keys, e.g.,
61
+
62
+ ```
63
+ ANTHROPIC_API_KEY=your_anthropic_api_key
64
+ ```
65
+
66
+ ### Try it out
67
+
68
+ #### Jupyter Notebook Example
69
+ [Notebook Link](https://github.com/grasp-technologies/grasp-agents/blob/master/src/grasp_agents/examples/notebooks/agents_demo.ipynb)
70
+
71
+ #### A Grasp-Agents Powered Web App
72
+ [https://grasp.study/](https://grasp.study/)
73
+
74
+ #### Script Example
75
+
76
+ Create a script, e.g., `problem_recommender.py`:
77
+
78
+ ```python
79
+ import asyncio
80
+ from typing import Any
81
+
82
+ from dotenv import load_dotenv
83
+ from pydantic import BaseModel
84
+
85
+ from grasp_agents import BaseTool, LLMAgent, RunContext
86
+ from grasp_agents.litellm import LiteLLM, LiteLLMSettings
87
+ from grasp_agents.printer import print_event_stream
88
+ from grasp_agents.typing.events import ProcPacketOutEvent
89
+
90
+ load_dotenv()
91
+
92
+ sys_prompt = """
93
+ Your task is to suggest an exciting stats problem to the student.
94
+ You should first ask the student about their education, interests, and preferences, then suggest a problem tailored specifically to them.
95
+
96
+ # Instructions
97
+ * Use the provided tool to ask questions.
98
+ * Ask questions one by one.
99
+ * The problem must have all the necessary data.
100
+ * Use the final answer tool to provide the problem.
101
+ """
102
+
103
+
104
+ class TeacherQuestion(BaseModel):
105
+ question: str
106
+
107
+
108
+ StudentReply = str
109
+
110
+
111
+ ask_student_tool_description = """
112
+ "Ask the student a question and get their reply."
113
+
114
+ Args:
115
+ question: str
116
+ The question to ask the student.
117
+ Returns:
118
+ reply: str
119
+ The student's reply to the question.
120
+ """
121
+
122
+
123
+ class AskStudentTool(BaseTool[TeacherQuestion, StudentReply, None]):
124
+ name: str = "ask_student"
125
+ description: str = ask_student_tool_description
126
+
127
+ async def run(self, inp: TeacherQuestion, **kwargs: Any) -> StudentReply:
128
+ return input(inp.question)
129
+
130
+
131
+ class Problem(BaseModel):
132
+ problem: str
133
+
134
+
135
+ teacher = LLMAgent[None, Problem, None](
136
+ name="teacher",
137
+ llm=LiteLLM(
138
+ model_name="claude-sonnet-4-5",
139
+ llm_settings=LiteLLMSettings(reasoning_effort="low"),
140
+ ),
141
+ tools=[AskStudentTool()],
142
+ final_answer_as_tool_call=True,
143
+ sys_prompt=sys_prompt,
144
+ stream_llm_responses=True,
145
+ )
146
+
147
+ async def main():
148
+ ctx = RunContext[None]()
149
+ async for event in print_event_stream(teacher.run_stream("start", ctx=ctx)):
150
+ if isinstance(event, ProcPacketOutEvent):
151
+ result = event.data.payloads[0]
152
+ print(f"\n<Suggested Problem>:\n\n{result.problem}\n")
153
+
154
+ asyncio.run(main())
155
+ ```
156
+
157
+ Run your script:
158
+
159
+ ```bash
160
+ uv run problem_recommender.py
161
+ ```
162
+
163
+ You can find more examples in [src/grasp_agents/examples/notebooks/agents_demo.ipynb](https://github.com/grasp-technologies/grasp-agents/tree/master/src/grasp_agents/examples/notebooks/agents_demo.ipynb).
@@ -0,0 +1,59 @@
1
+ [project]
2
+ name = "grasp_agents_legacy"
3
+ version = "0.6.50"
4
+ description = "Grasp Agents Library"
5
+ readme = "README.md"
6
+ requires-python = ">=3.11.4,<4"
7
+ dependencies = [
8
+ "httpx>=0.27.0,<1",
9
+ "openai>=1.68.2,<3",
10
+ "tenacity>=8.3.0,<9",
11
+ "tqdm>=4.66.2,<5",
12
+ "pyyaml>=6.0.2",
13
+ "pydantic>=2",
14
+ "litellm==1.83.10",
15
+ "opentelemetry-sdk>=1.37.0",
16
+ "traceloop-sdk>=0.47.2",
17
+ "termcolor>=2.4.0,<3",
18
+ "python-dotenv>=1.0",
19
+ "google-genai>=1.45.0",
20
+ "numpy<2",
21
+ ]
22
+
23
+ [dependency-groups]
24
+ dev = [
25
+ "ipython>=8.3.0,<9",
26
+ "ipykernel>=6.19.1,<7",
27
+ "ipywidgets>=8.0.4,<9",
28
+ "widgetsnbextension>=4.0.5,<5",
29
+ "types-cachetools>=5.0.1,<6",
30
+ "pre-commit-uv>=4.1.4",
31
+ "twine>=5.1.1,<6",
32
+ "ruff>=0.11.8",
33
+ "pyright>=1.1.400",
34
+ "pip-licenses>=5.0.0",
35
+ "pytest>=8,<9",
36
+ ]
37
+
38
+ [project.optional-dependencies]
39
+ observability = [
40
+ "arize-phoenix-otel>=0.13.1",
41
+ "openinference-instrumentation-openllmetry>=0.1.2",
42
+ "openinference-instrumentation-openai>=0.1.32",
43
+ "openinference-instrumentation-litellm>=0.1.25",
44
+ ]
45
+
46
+ [build-system]
47
+ requires = ["hatchling"]
48
+ build-backend = "hatchling.build"
49
+
50
+ [tool.hatch.build.targets.sdist]
51
+ include = ["src/grasp_agents_legacy"]
52
+ exclude = ["src/grasp_agents_legacy/examples", "*.ipynb"]
53
+
54
+ [tool.hatch.build.targets.wheel]
55
+ packages = ["src/grasp_agents_legacy"]
56
+ exclude = ["src/grasp_agents_legacy/examples", "*.ipynb"]
57
+
58
+ [tool.hatch.metadata]
59
+ allow-direct-references = true
@@ -0,0 +1,44 @@
1
+ # pyright: reportUnusedImport=false
2
+
3
+
4
+ from .llm import LLM, LLMSettings
5
+ from .llm_agent import LLMAgent
6
+ from .llm_agent_memory import LLMAgentMemory
7
+ from .memory import Memory
8
+ from .packet import Packet
9
+ from .printer import Printer, print_event_stream
10
+ from .processors.base_processor import BaseProcessor
11
+ from .processors.parallel_processor import ParallelProcessor
12
+ from .processors.processor import Processor
13
+ from .run_context import RunContext
14
+ from .typing.completion import Completion
15
+ from .typing.content import Content, ImageData
16
+ from .typing.io import LLMPrompt, ProcName
17
+ from .typing.message import AssistantMessage, Messages, SystemMessage, UserMessage
18
+ from .typing.tool import BaseTool
19
+
20
+ __all__ = [
21
+ "LLM",
22
+ "AssistantMessage",
23
+ "BaseProcessor",
24
+ "BaseTool",
25
+ "Completion",
26
+ "Content",
27
+ "ImageData",
28
+ "LLMAgent",
29
+ "LLMAgentMemory",
30
+ "LLMPrompt",
31
+ "LLMSettings",
32
+ "Memory",
33
+ "Messages",
34
+ "Packet",
35
+ "Packet",
36
+ "ParallelProcessor",
37
+ "Printer",
38
+ "ProcName",
39
+ "Processor",
40
+ "RunContext",
41
+ "SystemMessage",
42
+ "UserMessage",
43
+ "print_event_stream",
44
+ ]