agent-runtime-core 0.7.0__py3-none-any.whl → 0.8.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.
Files changed (38) hide show
  1. agent_runtime_core/__init__.py +109 -2
  2. agent_runtime_core/agentic_loop.py +254 -0
  3. agent_runtime_core/config.py +54 -4
  4. agent_runtime_core/config_schema.py +307 -0
  5. agent_runtime_core/files/__init__.py +88 -0
  6. agent_runtime_core/files/base.py +343 -0
  7. agent_runtime_core/files/ocr.py +406 -0
  8. agent_runtime_core/files/processors.py +508 -0
  9. agent_runtime_core/files/tools.py +317 -0
  10. agent_runtime_core/files/vision.py +360 -0
  11. agent_runtime_core/interfaces.py +106 -0
  12. agent_runtime_core/json_runtime.py +509 -0
  13. agent_runtime_core/llm/__init__.py +80 -7
  14. agent_runtime_core/llm/anthropic.py +133 -12
  15. agent_runtime_core/llm/models_config.py +180 -0
  16. agent_runtime_core/memory/__init__.py +70 -0
  17. agent_runtime_core/memory/manager.py +554 -0
  18. agent_runtime_core/memory/mixin.py +294 -0
  19. agent_runtime_core/multi_agent.py +569 -0
  20. agent_runtime_core/persistence/__init__.py +2 -0
  21. agent_runtime_core/persistence/file.py +277 -0
  22. agent_runtime_core/rag/__init__.py +65 -0
  23. agent_runtime_core/rag/chunking.py +224 -0
  24. agent_runtime_core/rag/indexer.py +253 -0
  25. agent_runtime_core/rag/retriever.py +261 -0
  26. agent_runtime_core/runner.py +193 -15
  27. agent_runtime_core/tool_calling_agent.py +88 -130
  28. agent_runtime_core/tools.py +179 -0
  29. agent_runtime_core/vectorstore/__init__.py +193 -0
  30. agent_runtime_core/vectorstore/base.py +138 -0
  31. agent_runtime_core/vectorstore/embeddings.py +242 -0
  32. agent_runtime_core/vectorstore/sqlite_vec.py +328 -0
  33. agent_runtime_core/vectorstore/vertex.py +295 -0
  34. {agent_runtime_core-0.7.0.dist-info → agent_runtime_core-0.8.0.dist-info}/METADATA +236 -1
  35. agent_runtime_core-0.8.0.dist-info/RECORD +63 -0
  36. agent_runtime_core-0.7.0.dist-info/RECORD +0 -39
  37. {agent_runtime_core-0.7.0.dist-info → agent_runtime_core-0.8.0.dist-info}/WHEEL +0 -0
  38. {agent_runtime_core-0.7.0.dist-info → agent_runtime_core-0.8.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,295 @@
1
+ """
2
+ Vertex AI Vector Search implementation.
3
+
4
+ Uses Google Cloud Vertex AI Vector Search for enterprise-scale vector similarity search.
5
+ Ideal for production deployments requiring managed infrastructure and high scalability.
6
+
7
+ Requires: pip install google-cloud-aiplatform
8
+
9
+ Note: Vertex AI Vector Search requires pre-created index and endpoint resources.
10
+ See: https://cloud.google.com/vertex-ai/docs/vector-search/overview
11
+ """
12
+
13
+ import json
14
+ from typing import Optional
15
+
16
+ from agent_runtime_core.vectorstore.base import (
17
+ VectorStore,
18
+ VectorRecord,
19
+ VectorSearchResult,
20
+ )
21
+
22
+
23
+ class VertexVectorStore(VectorStore):
24
+ """
25
+ Vector store using Google Vertex AI Vector Search.
26
+
27
+ This implementation uses Vertex AI's managed vector search service for
28
+ enterprise-scale similarity search. It's ideal for:
29
+ - Production deployments requiring high availability
30
+ - Large-scale datasets (billions of vectors)
31
+ - Applications already using Google Cloud
32
+
33
+ Important: This store requires pre-created Vertex AI resources:
34
+ 1. A Vector Search Index
35
+ 2. An Index Endpoint with the index deployed
36
+
37
+ The store maintains a local cache of content/metadata since Vertex AI
38
+ Vector Search only stores vectors and IDs. For production use, consider
39
+ using a separate database for content storage.
40
+ """
41
+
42
+ def __init__(
43
+ self,
44
+ project_id: str,
45
+ location: str,
46
+ index_endpoint_id: str,
47
+ deployed_index_id: str,
48
+ index_id: Optional[str] = None,
49
+ ):
50
+ """
51
+ Initialize Vertex AI Vector Search store.
52
+
53
+ Args:
54
+ project_id: Google Cloud project ID
55
+ location: Google Cloud region (e.g., "us-central1")
56
+ index_endpoint_id: The ID of the index endpoint
57
+ deployed_index_id: The ID of the deployed index
58
+ index_id: Optional index ID for batch updates
59
+ """
60
+ self._project_id = project_id
61
+ self._location = location
62
+ self._index_endpoint_id = index_endpoint_id
63
+ self._deployed_index_id = deployed_index_id
64
+ self._index_id = index_id
65
+ self._endpoint = None
66
+ self._initialized = False
67
+
68
+ # Local cache for content and metadata
69
+ # In production, use a proper database
70
+ self._content_cache: dict[str, tuple[str, dict]] = {}
71
+
72
+ def _ensure_initialized(self) -> None:
73
+ """Initialize Vertex AI SDK and get endpoint."""
74
+ if self._initialized:
75
+ return
76
+ try:
77
+ from google.cloud import aiplatform
78
+ from google.cloud.aiplatform.matching_engine import MatchingEngineIndexEndpoint
79
+ except ImportError:
80
+ raise ImportError(
81
+ "Google Cloud AI Platform package not installed. "
82
+ "Install with: pip install google-cloud-aiplatform"
83
+ )
84
+
85
+ aiplatform.init(project=self._project_id, location=self._location)
86
+
87
+ # Get the index endpoint
88
+ endpoint_resource_name = (
89
+ f"projects/{self._project_id}/locations/{self._location}/"
90
+ f"indexEndpoints/{self._index_endpoint_id}"
91
+ )
92
+ self._endpoint = MatchingEngineIndexEndpoint(endpoint_resource_name)
93
+ self._initialized = True
94
+
95
+ async def add(
96
+ self,
97
+ id: str,
98
+ vector: list[float],
99
+ content: str,
100
+ metadata: Optional[dict] = None,
101
+ ) -> None:
102
+ """
103
+ Add a vector with its content and metadata.
104
+
105
+ Note: For Vertex AI, vectors are typically added through batch operations
106
+ to the index. This method adds to a local cache and should be followed
107
+ by a batch update to the index.
108
+ """
109
+ self._ensure_initialized()
110
+
111
+ # Store content and metadata locally
112
+ self._content_cache[id] = (content, metadata or {})
113
+
114
+ # For single adds, we use the streaming update API if available
115
+ # This requires the index to support streaming updates
116
+ if self._index_id:
117
+ import asyncio
118
+ from google.cloud import aiplatform
119
+
120
+ index_resource_name = (
121
+ f"projects/{self._project_id}/locations/{self._location}/"
122
+ f"indexes/{self._index_id}"
123
+ )
124
+ index = aiplatform.MatchingEngineIndex(index_resource_name)
125
+
126
+ # Prepare datapoint
127
+ datapoint = {
128
+ "datapoint_id": id,
129
+ "feature_vector": vector,
130
+ }
131
+
132
+ # Run in executor since SDK is synchronous
133
+ loop = asyncio.get_event_loop()
134
+ await loop.run_in_executor(
135
+ None,
136
+ lambda: index.upsert_datapoints(datapoints=[datapoint]),
137
+ )
138
+
139
+ async def add_batch(
140
+ self,
141
+ items: list[tuple[str, list[float], str, Optional[dict]]],
142
+ ) -> None:
143
+ """Add multiple vectors efficiently."""
144
+ if not items:
145
+ return
146
+
147
+ self._ensure_initialized()
148
+
149
+ # Store content and metadata locally
150
+ for id, _, content, metadata in items:
151
+ self._content_cache[id] = (content, metadata or {})
152
+
153
+ if self._index_id:
154
+ import asyncio
155
+ from google.cloud import aiplatform
156
+
157
+ index_resource_name = (
158
+ f"projects/{self._project_id}/locations/{self._location}/"
159
+ f"indexes/{self._index_id}"
160
+ )
161
+ index = aiplatform.MatchingEngineIndex(index_resource_name)
162
+
163
+ # Prepare datapoints
164
+ datapoints = [
165
+ {"datapoint_id": id, "feature_vector": vector}
166
+ for id, vector, _, _ in items
167
+ ]
168
+
169
+ # Run in executor since SDK is synchronous
170
+ loop = asyncio.get_event_loop()
171
+ await loop.run_in_executor(
172
+ None,
173
+ lambda: index.upsert_datapoints(datapoints=datapoints),
174
+ )
175
+
176
+ async def search(
177
+ self,
178
+ query_vector: list[float],
179
+ limit: int = 10,
180
+ filter: Optional[dict] = None,
181
+ ) -> list[VectorSearchResult]:
182
+ """Search for similar vectors."""
183
+ self._ensure_initialized()
184
+ import asyncio
185
+
186
+ # Vertex AI Vector Search uses find_neighbors for queries
187
+ loop = asyncio.get_event_loop()
188
+
189
+ # Build the query
190
+ queries = [query_vector]
191
+
192
+ # Execute search
193
+ response = await loop.run_in_executor(
194
+ None,
195
+ lambda: self._endpoint.find_neighbors(
196
+ deployed_index_id=self._deployed_index_id,
197
+ queries=queries,
198
+ num_neighbors=limit,
199
+ ),
200
+ )
201
+
202
+ results = []
203
+ if response and len(response) > 0:
204
+ for neighbor in response[0]:
205
+ id = neighbor.id
206
+ # Vertex AI returns distance, convert to similarity
207
+ # Using cosine similarity: score = 1 - distance for normalized vectors
208
+ score = 1.0 - neighbor.distance if hasattr(neighbor, "distance") else 0.0
209
+
210
+ # Get content and metadata from cache
211
+ content, metadata = self._content_cache.get(id, ("", {}))
212
+
213
+ # Apply filter if provided
214
+ if filter:
215
+ match = all(
216
+ metadata.get(k) == v for k, v in filter.items()
217
+ )
218
+ if not match:
219
+ continue
220
+
221
+ results.append(
222
+ VectorSearchResult(
223
+ id=id,
224
+ content=content,
225
+ score=score,
226
+ metadata=metadata,
227
+ )
228
+ )
229
+
230
+ return results
231
+
232
+ async def delete(self, id: str) -> bool:
233
+ """Delete a vector by ID."""
234
+ self._ensure_initialized()
235
+
236
+ # Remove from local cache
237
+ existed = id in self._content_cache
238
+ self._content_cache.pop(id, None)
239
+
240
+ # Delete from index if index_id is provided
241
+ if self._index_id:
242
+ import asyncio
243
+ from google.cloud import aiplatform
244
+
245
+ index_resource_name = (
246
+ f"projects/{self._project_id}/locations/{self._location}/"
247
+ f"indexes/{self._index_id}"
248
+ )
249
+ index = aiplatform.MatchingEngineIndex(index_resource_name)
250
+
251
+ loop = asyncio.get_event_loop()
252
+ await loop.run_in_executor(
253
+ None,
254
+ lambda: index.remove_datapoints(datapoint_ids=[id]),
255
+ )
256
+
257
+ return existed
258
+
259
+ async def delete_by_filter(self, filter: dict) -> int:
260
+ """Delete vectors matching filter."""
261
+ # Find matching IDs from cache
262
+ ids_to_delete = []
263
+ for id, (_, metadata) in self._content_cache.items():
264
+ if all(metadata.get(k) == v for k, v in filter.items()):
265
+ ids_to_delete.append(id)
266
+
267
+ # Delete each matching ID
268
+ for id in ids_to_delete:
269
+ await self.delete(id)
270
+
271
+ return len(ids_to_delete)
272
+
273
+ async def get(self, id: str) -> Optional[VectorRecord]:
274
+ """
275
+ Get a vector by ID.
276
+
277
+ Note: Vertex AI Vector Search doesn't support direct vector retrieval.
278
+ This returns cached content/metadata with an empty vector.
279
+ """
280
+ if id not in self._content_cache:
281
+ return None
282
+
283
+ content, metadata = self._content_cache[id]
284
+ return VectorRecord(
285
+ id=id,
286
+ vector=[], # Vertex AI doesn't support vector retrieval
287
+ content=content,
288
+ metadata=metadata,
289
+ )
290
+
291
+ async def close(self) -> None:
292
+ """Close connections."""
293
+ self._endpoint = None
294
+ self._initialized = False
295
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-runtime-core
3
- Version: 0.7.0
3
+ Version: 0.8.0
4
4
  Summary: Framework-agnostic Python library for executing AI agents with consistent patterns
5
5
  Project-URL: Homepage, https://github.com/makemore/agent-runtime-core
6
6
  Project-URL: Repository, https://github.com/makemore/agent-runtime-core
@@ -19,10 +19,21 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
19
  Requires-Python: >=3.11
20
20
  Provides-Extra: all
21
21
  Requires-Dist: anthropic>=0.18.0; extra == 'all'
22
+ Requires-Dist: azure-ai-formrecognizer>=3.3.0; extra == 'all'
23
+ Requires-Dist: boto3>=1.34.0; extra == 'all'
24
+ Requires-Dist: google-cloud-aiplatform>=1.38.0; extra == 'all'
25
+ Requires-Dist: google-cloud-vision>=3.0.0; extra == 'all'
26
+ Requires-Dist: google-generativeai>=0.4.0; extra == 'all'
22
27
  Requires-Dist: langfuse>=2.0.0; extra == 'all'
23
28
  Requires-Dist: litellm>=1.0.0; extra == 'all'
24
29
  Requires-Dist: openai>=1.0.0; extra == 'all'
30
+ Requires-Dist: openpyxl>=3.1.0; extra == 'all'
31
+ Requires-Dist: pillow>=10.0.0; extra == 'all'
32
+ Requires-Dist: pypdf>=4.0.0; extra == 'all'
33
+ Requires-Dist: pytesseract>=0.3.10; extra == 'all'
34
+ Requires-Dist: python-docx>=1.0.0; extra == 'all'
25
35
  Requires-Dist: redis>=5.0.0; extra == 'all'
36
+ Requires-Dist: sqlite-vec>=0.1.0; extra == 'all'
26
37
  Provides-Extra: anthropic
27
38
  Requires-Dist: anthropic>=0.18.0; extra == 'anthropic'
28
39
  Provides-Extra: dev
@@ -31,14 +42,42 @@ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
31
42
  Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
32
43
  Requires-Dist: pytest>=8.0.0; extra == 'dev'
33
44
  Requires-Dist: ruff>=0.1.0; extra == 'dev'
45
+ Provides-Extra: files
46
+ Requires-Dist: openpyxl>=3.1.0; extra == 'files'
47
+ Requires-Dist: pillow>=10.0.0; extra == 'files'
48
+ Requires-Dist: pypdf>=4.0.0; extra == 'files'
49
+ Requires-Dist: python-docx>=1.0.0; extra == 'files'
50
+ Provides-Extra: files-all
51
+ Requires-Dist: azure-ai-formrecognizer>=3.3.0; extra == 'files-all'
52
+ Requires-Dist: boto3>=1.34.0; extra == 'files-all'
53
+ Requires-Dist: google-cloud-vision>=3.0.0; extra == 'files-all'
54
+ Requires-Dist: google-generativeai>=0.4.0; extra == 'files-all'
55
+ Requires-Dist: openpyxl>=3.1.0; extra == 'files-all'
56
+ Requires-Dist: pillow>=10.0.0; extra == 'files-all'
57
+ Requires-Dist: pypdf>=4.0.0; extra == 'files-all'
58
+ Requires-Dist: pytesseract>=0.3.10; extra == 'files-all'
59
+ Requires-Dist: python-docx>=1.0.0; extra == 'files-all'
34
60
  Provides-Extra: langfuse
35
61
  Requires-Dist: langfuse>=2.0.0; extra == 'langfuse'
36
62
  Provides-Extra: litellm
37
63
  Requires-Dist: litellm>=1.0.0; extra == 'litellm'
64
+ Provides-Extra: ocr
65
+ Requires-Dist: azure-ai-formrecognizer>=3.3.0; extra == 'ocr'
66
+ Requires-Dist: boto3>=1.34.0; extra == 'ocr'
67
+ Requires-Dist: google-cloud-vision>=3.0.0; extra == 'ocr'
68
+ Requires-Dist: pytesseract>=0.3.10; extra == 'ocr'
38
69
  Provides-Extra: openai
39
70
  Requires-Dist: openai>=1.0.0; extra == 'openai'
40
71
  Provides-Extra: redis
41
72
  Requires-Dist: redis>=5.0.0; extra == 'redis'
73
+ Provides-Extra: sqlite-vec
74
+ Requires-Dist: sqlite-vec>=0.1.0; extra == 'sqlite-vec'
75
+ Provides-Extra: vertex
76
+ Requires-Dist: google-cloud-aiplatform>=1.38.0; extra == 'vertex'
77
+ Provides-Extra: vision
78
+ Requires-Dist: anthropic>=0.18.0; extra == 'vision'
79
+ Requires-Dist: google-generativeai>=0.4.0; extra == 'vision'
80
+ Requires-Dist: openai>=1.0.0; extra == 'vision'
42
81
  Description-Content-Type: text/markdown
43
82
 
44
83
  # agent-runtime-core
@@ -53,6 +92,8 @@ A lightweight, framework-agnostic Python library for building AI agent systems.
53
92
 
54
93
  | Version | Date | Changes |
55
94
  |---------|------|---------|
95
+ | **0.8.0** | 2026-01-28 | **File Ingestion** - Pluggable file processors (PDF, images, DOCX, XLSX, CSV), OCR providers (Tesseract, Google Vision, AWS Textract, Azure), AI vision (OpenAI, Anthropic, Gemini), file read/write tools |
96
+ | **0.7.1** | 2026-01-24 | RAG module, vector stores (sqlite-vec, Vertex AI), memory system, multi-agent support, agentic loop, JSON runtime |
56
97
  | **0.6.0** | 2025-01-23 | Enhanced registry with factory functions and class registration |
57
98
  | **0.5.2** | 2025-01-14 | Add ToolCallingAgent base class, execute_with_events helper |
58
99
  | **0.5.1** | 2025-01-13 | Bug fixes and improvements |
@@ -820,6 +861,200 @@ The executor emits events for observability:
820
861
  - `EventType.STEP_SKIPPED` - Step skipped (already completed)
821
862
  - `EventType.PROGRESS_UPDATE` - Progress percentage update
822
863
 
864
+ ## Multi-Agent Systems
865
+
866
+ The `multi_agent` module provides the "agent-as-tool" pattern, allowing agents to invoke other agents as tools. This enables router/dispatcher patterns, hierarchical agent systems, and specialist delegation.
867
+
868
+ ### Core Concepts
869
+
870
+ **Invocation Modes:**
871
+ - `DELEGATE`: Sub-agent runs and returns result to parent (parent continues). Good for "get me an answer".
872
+ - `HANDOFF`: Control transfers completely to sub-agent (parent exits). Good for "transfer this customer to billing".
873
+
874
+ **Context Modes:**
875
+ - `FULL`: Complete conversation history passed to sub-agent (default)
876
+ - `SUMMARY`: Summarized context + current message (more efficient)
877
+ - `MESSAGE_ONLY`: Only the invocation message (clean isolation)
878
+
879
+ ### Creating Agent Tools
880
+
881
+ Wrap any agent as a tool that can be called by other agents:
882
+
883
+ ```python
884
+ from agent_runtime_core.multi_agent import (
885
+ AgentTool,
886
+ InvocationMode,
887
+ ContextMode,
888
+ invoke_agent,
889
+ register_agent_tools,
890
+ )
891
+
892
+ # Define specialist agents
893
+ class BillingAgent(AgentRuntime):
894
+ @property
895
+ def key(self) -> str:
896
+ return "billing-specialist"
897
+
898
+ async def run(self, ctx: RunContext) -> RunResult:
899
+ # Handle billing questions, refunds, payments
900
+ ...
901
+
902
+ class TechSupportAgent(AgentRuntime):
903
+ @property
904
+ def key(self) -> str:
905
+ return "tech-support"
906
+
907
+ async def run(self, ctx: RunContext) -> RunResult:
908
+ # Handle technical issues
909
+ ...
910
+
911
+ # Wrap agents as tools
912
+ billing_tool = AgentTool(
913
+ agent=BillingAgent(),
914
+ name="billing_specialist",
915
+ description="Handles billing questions, refunds, and payment issues. Use when customer has billing-related questions.",
916
+ invocation_mode=InvocationMode.DELEGATE,
917
+ context_mode=ContextMode.FULL,
918
+ )
919
+
920
+ tech_support_tool = AgentTool(
921
+ agent=TechSupportAgent(),
922
+ name="tech_support",
923
+ description="Handles technical issues and troubleshooting. Use for technical problems.",
924
+ invocation_mode=InvocationMode.HANDOFF, # Transfer control completely
925
+ )
926
+ ```
927
+
928
+ ### Router Agent Pattern
929
+
930
+ Create a router agent that delegates to specialists:
931
+
932
+ ```python
933
+ class RouterAgent(AgentRuntime):
934
+ """Routes customer requests to appropriate specialist agents."""
935
+
936
+ def __init__(self):
937
+ self.agent_tools = [billing_tool, tech_support_tool]
938
+
939
+ @property
940
+ def key(self) -> str:
941
+ return "customer-router"
942
+
943
+ async def run(self, ctx: RunContext) -> RunResult:
944
+ from agent_runtime_core.llm import get_llm_client
945
+ llm = get_llm_client()
946
+
947
+ # Create tool registry with agent-tools
948
+ tools = ToolRegistry()
949
+ messages = list(ctx.input_messages)
950
+
951
+ # Register agent-tools as callable tools
952
+ register_agent_tools(
953
+ registry=tools,
954
+ agent_tools=self.agent_tools,
955
+ get_conversation_history=lambda: messages,
956
+ parent_ctx=ctx,
957
+ )
958
+
959
+ # Add system prompt for routing
960
+ system_message = {
961
+ "role": "system",
962
+ "content": """You are a customer service router. Analyze the customer's
963
+ request and delegate to the appropriate specialist:
964
+ - billing_specialist: For billing, payments, refunds
965
+ - tech_support: For technical issues (this will transfer the customer)
966
+
967
+ If you can answer directly, do so. Otherwise, use the appropriate tool."""
968
+ }
969
+
970
+ while True:
971
+ response = await llm.generate(
972
+ [system_message] + messages,
973
+ tools=tools.to_openai_format(),
974
+ )
975
+
976
+ messages.append(response.message)
977
+
978
+ if not response.tool_calls:
979
+ # No tool call - respond directly
980
+ await ctx.emit(EventType.ASSISTANT_MESSAGE, {
981
+ "content": response.content,
982
+ })
983
+ break
984
+
985
+ # Execute tool calls (which may invoke sub-agents)
986
+ for tool_call in response.tool_calls:
987
+ result = await tools.execute_with_events(tool_call, ctx)
988
+
989
+ # Check for handoff
990
+ if isinstance(result, dict) and result.get("handoff"):
991
+ # Sub-agent took over - we're done
992
+ return RunResult(
993
+ final_output=result.get("final_output", {}),
994
+ final_messages=messages,
995
+ )
996
+
997
+ # Add result to conversation
998
+ messages.append({
999
+ "role": "tool",
1000
+ "tool_call_id": tool_call.id,
1001
+ "content": str(result.get("response", result)),
1002
+ })
1003
+
1004
+ return RunResult(
1005
+ final_output={"response": response.content},
1006
+ final_messages=messages,
1007
+ )
1008
+ ```
1009
+
1010
+ ### Direct Invocation
1011
+
1012
+ You can also invoke agents directly without the tool pattern:
1013
+
1014
+ ```python
1015
+ from agent_runtime_core.multi_agent import invoke_agent
1016
+
1017
+ # Invoke a sub-agent directly
1018
+ result = await invoke_agent(
1019
+ agent_tool=billing_tool,
1020
+ message="Customer wants a refund for order #123",
1021
+ parent_ctx=ctx,
1022
+ conversation_history=messages,
1023
+ additional_context="Customer has been waiting 2 weeks",
1024
+ )
1025
+
1026
+ if result.handoff:
1027
+ # Sub-agent took over
1028
+ return RunResult(final_output=result.run_result.final_output)
1029
+ else:
1030
+ # Use the response
1031
+ print(result.response)
1032
+ ```
1033
+
1034
+ ### Events
1035
+
1036
+ Multi-agent invocations emit events for observability:
1037
+
1038
+ - `sub_agent.start` - Sub-agent invocation started
1039
+ - `sub_agent.end` - Sub-agent invocation completed
1040
+ - `tool.call` with `is_agent_tool: true` - Agent-tool was called
1041
+ - `tool.result` with `is_agent_tool: true` - Agent-tool returned
1042
+
1043
+ ### AgentTool Options
1044
+
1045
+ ```python
1046
+ AgentTool(
1047
+ agent=my_agent, # Required: The agent to wrap
1048
+ name="specialist", # Required: Tool name
1049
+ description="When to use this agent", # Required: Shown to parent LLM
1050
+ invocation_mode=InvocationMode.DELEGATE, # DELEGATE or HANDOFF
1051
+ context_mode=ContextMode.FULL, # FULL, SUMMARY, or MESSAGE_ONLY
1052
+ max_turns=10, # Optional: Limit sub-agent turns
1053
+ input_schema={...}, # Optional: Custom input schema
1054
+ metadata={"category": "billing"}, # Optional: Additional metadata
1055
+ )
1056
+ ```
1057
+
823
1058
  ## API Reference
824
1059
 
825
1060
  ### Configuration
@@ -0,0 +1,63 @@
1
+ agent_runtime_core/__init__.py,sha256=Vn-32GMh-6S5k6e4fiejAbNxjnbsoskf-Um1Ni2dgog,7117
2
+ agent_runtime_core/agentic_loop.py,sha256=DJ3RXaQLFlHMf-icQjpTJkAvdfjkPBSGN1S_iy3mf64,9635
3
+ agent_runtime_core/config.py,sha256=WVfcIluFvf2zC_NKk2WuJhhPIGQNcuxmZV9TCg4t13o,7297
4
+ agent_runtime_core/config_schema.py,sha256=1t2ZF5Rk2oRbeYpRATMdFgbvgTPtedIQO6xej4cELh0,10576
5
+ agent_runtime_core/contexts.py,sha256=41UVkSqRJ3E9yIxfCQ-BQ7-wetUfSnDNGdr5-dQOWiY,11349
6
+ agent_runtime_core/interfaces.py,sha256=QvRFPRc2Fwqv_sv-3nExCoaiqwBf_HsQo9yzCYE_Hm0,15498
7
+ agent_runtime_core/json_runtime.py,sha256=b1BnGAQMORB4YULsKcCR0hEaCvln3Bz2dP228yq5BIQ,17358
8
+ agent_runtime_core/multi_agent.py,sha256=UleIFocGW0GZFeoa_bPfYGLZZH-NYiEsiG2BBTGdKyA,18409
9
+ agent_runtime_core/registry.py,sha256=QmazCAcHTsPt236Z_xEBJjdppm6jUuufE-gfvcGMUCk,3959
10
+ agent_runtime_core/runner.py,sha256=ydzyGJHCyz1wjs-sN5dx4RlJsYK0U-Or12BL_Fg8-aQ,19595
11
+ agent_runtime_core/steps.py,sha256=XpVFK7P-ZOpr7NwaP7XFygduIpjrKld-OIig7dHNMKE,11994
12
+ agent_runtime_core/testing.py,sha256=ordECGprBappLBMWxlETvuf2AoIPNomJFeSedXaY30E,11131
13
+ agent_runtime_core/tool_calling_agent.py,sha256=kyPTwHlYGaqUo0HJ7ycYCCQMFHD_AmPZMsyjxaKpJVc,5967
14
+ agent_runtime_core/tools.py,sha256=SSbiViOJe7raSijwV_TSHI60F5ReHy43Vd_QrAkKgAk,5620
15
+ agent_runtime_core/events/__init__.py,sha256=Gg7cMQHWfLTQ4Xik09KSg7cWbQDmW_MuF5_jl-yZkHU,1575
16
+ agent_runtime_core/events/base.py,sha256=NfHYyoczxr40Er5emROi_aY_07m5hDrKsn31pdWY2DY,1950
17
+ agent_runtime_core/events/memory.py,sha256=9z4tY8XB8xDg3ybHsIwilOcRo7HY-vB-8vxiz6O54BE,2491
18
+ agent_runtime_core/events/redis.py,sha256=7PsUO2-iqrdGCJZUOq1IdzwDdNhqT5mwEnH5xy2Fklo,5874
19
+ agent_runtime_core/events/sqlite.py,sha256=ZpGgeuQujYT8pkDsiXDoFXTcBf2KqzoWX4D4J9xkmeE,5097
20
+ agent_runtime_core/files/__init__.py,sha256=VKhFWGtIDeXUP96DT7Du_vHKvu8aRCogm-LLSbAtZT4,1840
21
+ agent_runtime_core/files/base.py,sha256=RxAx1msYWy11sV6IDn6J7eVim29n_mHV7FF0gLi5Rjc,9742
22
+ agent_runtime_core/files/ocr.py,sha256=K1RU1JYo10SEtzC7tQymahZhvELvO3L2R_5fXL-rbxo,12111
23
+ agent_runtime_core/files/processors.py,sha256=KudeacTDxaVyUtCjBpIg1OuByi4_71WP9RDpBGQdx3U,14527
24
+ agent_runtime_core/files/tools.py,sha256=Dky2CxFLUL8GICIwU1kbNV-IwnszWr1WXhJ3FItGRd4,10856
25
+ agent_runtime_core/files/vision.py,sha256=nM8xKx-yEblwPFr5tM9JRrFkitTPLDkLU1fSDHLvuW8,10119
26
+ agent_runtime_core/llm/__init__.py,sha256=7-tA1FmPkhY1l-lHhzd84MQf2bjs26bcgb8oAlglc58,4605
27
+ agent_runtime_core/llm/anthropic.py,sha256=AX2QJoQf-4uLDCxWFs71XfD11IMN6iI3gMPA25F3KrM,12239
28
+ agent_runtime_core/llm/litellm_client.py,sha256=c-O-lE08cT3ne0xSOvSDezPL6hCiA69p3HnB451Ipe4,5193
29
+ agent_runtime_core/llm/models_config.py,sha256=i275wtsWeR-LHdFrObPI19PtCIGvMDKTEKpue5TuYIk,5342
30
+ agent_runtime_core/llm/openai.py,sha256=qBZkkndDgYQ6LG-9bHS2za5KJTGSgL-c_7h0bD3_5lg,6862
31
+ agent_runtime_core/memory/__init__.py,sha256=7dgoXMr3IIjKsKKbxVgQBrrhZHqmJRIx64mcbF8jgUM,2178
32
+ agent_runtime_core/memory/manager.py,sha256=ba8ZKb1aF9Pc-zZB4O_22b6zb6ELpvo_LhpSs959L5U,18474
33
+ agent_runtime_core/memory/mixin.py,sha256=Afq7rhW1SmZgii6b3gUbM3peDzMwfMxQ0DstHzGfuDM,9683
34
+ agent_runtime_core/persistence/__init__.py,sha256=HdkGW5hnLjBRE0QcUWVjL2xsIkMyKPpqJKpamPbFh0s,2822
35
+ agent_runtime_core/persistence/base.py,sha256=k0wuzTCffPJ609dj9hIhnaqnNI1Qr3pCzJ-6E1YkSRU,21616
36
+ agent_runtime_core/persistence/file.py,sha256=uZxl3W405jeX1H6f0Xj_pZOQFTpZOYbpIdJ98rZabBI,28712
37
+ agent_runtime_core/persistence/manager.py,sha256=UL_eFsFM28nXM6O9PTHdzKX9Qxh9v2gBGd1m9Bs0vog,14309
38
+ agent_runtime_core/queue/__init__.py,sha256=m8gapXACPGApLj0RIDpVe5cQYuvKq1QsY2_mXzZcULQ,1527
39
+ agent_runtime_core/queue/base.py,sha256=QW1eWbwBX_tmVD8yJobFJtlxLd_RtUWHTuXGessuxy8,3959
40
+ agent_runtime_core/queue/memory.py,sha256=G65NJ2QU8sB2WQ7myHXc8LzSFowEzBXtCt78WmhvxO8,5416
41
+ agent_runtime_core/queue/redis.py,sha256=x9BEoeh6cVcWdaziFSQZHUvq_bHN1WYHWw17HIEWi5o,15622
42
+ agent_runtime_core/queue/sqlite.py,sha256=3YwkU0QOcmAxYBpbfEB9xk8f-e2C3QcHK_RnPZvdick,14338
43
+ agent_runtime_core/rag/__init__.py,sha256=ilsbzkcycLlhLa0BCCpdMb0EGnLaC-l52EH3xIyN6vw,1845
44
+ agent_runtime_core/rag/chunking.py,sha256=wlFa_K4G1Mbkyy-g-JR67e4Xwb3-ysCmf8s1ar7s5Ls,6364
45
+ agent_runtime_core/rag/indexer.py,sha256=BWq_BysZD1rMkAD_30mLe6qk6cDkut05DpfmrWMSLQc,8003
46
+ agent_runtime_core/rag/retriever.py,sha256=-svCtkTL5n65KALssWM1MwxsTa4wIiUQKRf3j9GPrTM,8304
47
+ agent_runtime_core/state/__init__.py,sha256=RK16Sj1QPW0SNxtmESlLRMpFBY_hZbMGGNnvcLbdcWw,1564
48
+ agent_runtime_core/state/base.py,sha256=NqE3B0ySa-U2jkelgmkBbkmkaIQxfu4pDryoxkZTMrc,1593
49
+ agent_runtime_core/state/memory.py,sha256=yEGwoR25zWcoxL79_gEu38P_dHvjJOTGij2wxqZ7X9A,1566
50
+ agent_runtime_core/state/redis.py,sha256=VXY6ULEphehHVq4zSw5Y4AMCibm9Ghvzk7PqCrgStDg,3430
51
+ agent_runtime_core/state/sqlite.py,sha256=HKZwDiC_7F1W8Z_Pz8roEs91XhQ9rUHfGpuQ7WWt_NQ,4873
52
+ agent_runtime_core/tracing/__init__.py,sha256=u1QicGc39e30gWyQD4cQWxGGjITnkwoOPUhNrG6aNyI,1266
53
+ agent_runtime_core/tracing/langfuse.py,sha256=Rj2sUlatk5sFro0y68tw5X6fQcSwWxcBOSOjB0F7JTU,3660
54
+ agent_runtime_core/tracing/noop.py,sha256=SpsbpsUcNG6C3xZG3uyiNPUHY8etloISx3w56Q8D3KE,751
55
+ agent_runtime_core/vectorstore/__init__.py,sha256=HO6B2TsHTPMkHvRf-774IgVtVcrOf_5P-yUPRpYIUj4,5688
56
+ agent_runtime_core/vectorstore/base.py,sha256=y1ZZCbAMkFkbHwOqzaK0JUBAVjbnNwwdSnrxokzzvjQ,3426
57
+ agent_runtime_core/vectorstore/embeddings.py,sha256=WTTiId9Q6I7cxHuiInYHEV8EWS2HyRYRW1YDPALGUVY,7749
58
+ agent_runtime_core/vectorstore/sqlite_vec.py,sha256=B4KPYdSkm-af-uqltqMga1uXslC19Uaeuy1sXfKOjyo,10552
59
+ agent_runtime_core/vectorstore/vertex.py,sha256=a1Ps_gMYqTlWUkNALpgMVEX6r6Zw_8gN5pZ59-vH7Ww,9695
60
+ agent_runtime_core-0.8.0.dist-info/METADATA,sha256=nC_KSql_QyKBPfaGxyakWQhTR_z15gj3X068l7viqqY,32431
61
+ agent_runtime_core-0.8.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
62
+ agent_runtime_core-0.8.0.dist-info/licenses/LICENSE,sha256=fDlWep3_mUrj8KHV_jk275tHVEW7_9sJRhkNuGCZ_TA,1068
63
+ agent_runtime_core-0.8.0.dist-info/RECORD,,
@@ -1,39 +0,0 @@
1
- agent_runtime_core/__init__.py,sha256=2agzUmo3HGFMoj8K6xeXC0aWU_rrhU6kSt1HbtaVjnE,4380
2
- agent_runtime_core/config.py,sha256=e3_uB5brAuQcWU36sOhWF9R6RoJrngtCS-xEB3n2fas,4986
3
- agent_runtime_core/contexts.py,sha256=41UVkSqRJ3E9yIxfCQ-BQ7-wetUfSnDNGdr5-dQOWiY,11349
4
- agent_runtime_core/interfaces.py,sha256=T74pgS229tvarQD-_o25oflylUR7jq_jbgUjnvVs6IA,12191
5
- agent_runtime_core/registry.py,sha256=QmazCAcHTsPt236Z_xEBJjdppm6jUuufE-gfvcGMUCk,3959
6
- agent_runtime_core/runner.py,sha256=M3It72UhfmLt17jVnSvObiSfQ1_RN4JVUIJsjnRd2Ps,12771
7
- agent_runtime_core/steps.py,sha256=XpVFK7P-ZOpr7NwaP7XFygduIpjrKld-OIig7dHNMKE,11994
8
- agent_runtime_core/testing.py,sha256=ordECGprBappLBMWxlETvuf2AoIPNomJFeSedXaY30E,11131
9
- agent_runtime_core/tool_calling_agent.py,sha256=LY0lSI9GZbWoIKd-7NXFSvByAhvK6L625eOp01VbTrw,8525
10
- agent_runtime_core/events/__init__.py,sha256=Gg7cMQHWfLTQ4Xik09KSg7cWbQDmW_MuF5_jl-yZkHU,1575
11
- agent_runtime_core/events/base.py,sha256=NfHYyoczxr40Er5emROi_aY_07m5hDrKsn31pdWY2DY,1950
12
- agent_runtime_core/events/memory.py,sha256=9z4tY8XB8xDg3ybHsIwilOcRo7HY-vB-8vxiz6O54BE,2491
13
- agent_runtime_core/events/redis.py,sha256=7PsUO2-iqrdGCJZUOq1IdzwDdNhqT5mwEnH5xy2Fklo,5874
14
- agent_runtime_core/events/sqlite.py,sha256=ZpGgeuQujYT8pkDsiXDoFXTcBf2KqzoWX4D4J9xkmeE,5097
15
- agent_runtime_core/llm/__init__.py,sha256=LyFFDtk4HhvUXct0nTeKuYuWzVmVqLDSVRpnPArbGqY,2461
16
- agent_runtime_core/llm/anthropic.py,sha256=pt9QAjrv2dIPSAY3Pv6N_BzxL1tbhL-kPWsQ-DcHMLI,7516
17
- agent_runtime_core/llm/litellm_client.py,sha256=c-O-lE08cT3ne0xSOvSDezPL6hCiA69p3HnB451Ipe4,5193
18
- agent_runtime_core/llm/openai.py,sha256=qBZkkndDgYQ6LG-9bHS2za5KJTGSgL-c_7h0bD3_5lg,6862
19
- agent_runtime_core/persistence/__init__.py,sha256=l9_1Mzhy9_Y-IIKuBKTR3Z8r2TPyr0a6b1HEdyZf1_I,2772
20
- agent_runtime_core/persistence/base.py,sha256=k0wuzTCffPJ609dj9hIhnaqnNI1Qr3pCzJ-6E1YkSRU,21616
21
- agent_runtime_core/persistence/file.py,sha256=oDB4_ZQkwHTCT1uoqpw5jOleK69YXCQwlTPsW86Yb-I,17785
22
- agent_runtime_core/persistence/manager.py,sha256=UL_eFsFM28nXM6O9PTHdzKX9Qxh9v2gBGd1m9Bs0vog,14309
23
- agent_runtime_core/queue/__init__.py,sha256=m8gapXACPGApLj0RIDpVe5cQYuvKq1QsY2_mXzZcULQ,1527
24
- agent_runtime_core/queue/base.py,sha256=QW1eWbwBX_tmVD8yJobFJtlxLd_RtUWHTuXGessuxy8,3959
25
- agent_runtime_core/queue/memory.py,sha256=G65NJ2QU8sB2WQ7myHXc8LzSFowEzBXtCt78WmhvxO8,5416
26
- agent_runtime_core/queue/redis.py,sha256=x9BEoeh6cVcWdaziFSQZHUvq_bHN1WYHWw17HIEWi5o,15622
27
- agent_runtime_core/queue/sqlite.py,sha256=3YwkU0QOcmAxYBpbfEB9xk8f-e2C3QcHK_RnPZvdick,14338
28
- agent_runtime_core/state/__init__.py,sha256=RK16Sj1QPW0SNxtmESlLRMpFBY_hZbMGGNnvcLbdcWw,1564
29
- agent_runtime_core/state/base.py,sha256=NqE3B0ySa-U2jkelgmkBbkmkaIQxfu4pDryoxkZTMrc,1593
30
- agent_runtime_core/state/memory.py,sha256=yEGwoR25zWcoxL79_gEu38P_dHvjJOTGij2wxqZ7X9A,1566
31
- agent_runtime_core/state/redis.py,sha256=VXY6ULEphehHVq4zSw5Y4AMCibm9Ghvzk7PqCrgStDg,3430
32
- agent_runtime_core/state/sqlite.py,sha256=HKZwDiC_7F1W8Z_Pz8roEs91XhQ9rUHfGpuQ7WWt_NQ,4873
33
- agent_runtime_core/tracing/__init__.py,sha256=u1QicGc39e30gWyQD4cQWxGGjITnkwoOPUhNrG6aNyI,1266
34
- agent_runtime_core/tracing/langfuse.py,sha256=Rj2sUlatk5sFro0y68tw5X6fQcSwWxcBOSOjB0F7JTU,3660
35
- agent_runtime_core/tracing/noop.py,sha256=SpsbpsUcNG6C3xZG3uyiNPUHY8etloISx3w56Q8D3KE,751
36
- agent_runtime_core-0.7.0.dist-info/METADATA,sha256=-z-4oebI9V6-mq7wivGR-E-x0WS2dqE5exIz9jnE04M,23858
37
- agent_runtime_core-0.7.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
38
- agent_runtime_core-0.7.0.dist-info/licenses/LICENSE,sha256=fDlWep3_mUrj8KHV_jk275tHVEW7_9sJRhkNuGCZ_TA,1068
39
- agent_runtime_core-0.7.0.dist-info/RECORD,,