agent-runtime-core 0.7.0__tar.gz → 0.7.1__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.
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/PKG-INFO +202 -1
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/README.md +195 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/__init__.py +108 -1
- agent_runtime_core-0.7.1/agent_runtime_core/agentic_loop.py +254 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/config.py +54 -4
- agent_runtime_core-0.7.1/agent_runtime_core/config_schema.py +307 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/interfaces.py +106 -0
- agent_runtime_core-0.7.1/agent_runtime_core/json_runtime.py +509 -0
- agent_runtime_core-0.7.1/agent_runtime_core/llm/__init__.py +156 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/llm/anthropic.py +133 -12
- agent_runtime_core-0.7.1/agent_runtime_core/llm/models_config.py +180 -0
- agent_runtime_core-0.7.1/agent_runtime_core/memory/__init__.py +70 -0
- agent_runtime_core-0.7.1/agent_runtime_core/memory/manager.py +554 -0
- agent_runtime_core-0.7.1/agent_runtime_core/memory/mixin.py +294 -0
- agent_runtime_core-0.7.1/agent_runtime_core/multi_agent.py +569 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/persistence/__init__.py +2 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/persistence/file.py +277 -0
- agent_runtime_core-0.7.1/agent_runtime_core/rag/__init__.py +65 -0
- agent_runtime_core-0.7.1/agent_runtime_core/rag/chunking.py +224 -0
- agent_runtime_core-0.7.1/agent_runtime_core/rag/indexer.py +253 -0
- agent_runtime_core-0.7.1/agent_runtime_core/rag/retriever.py +261 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/runner.py +193 -15
- agent_runtime_core-0.7.1/agent_runtime_core/tool_calling_agent.py +214 -0
- agent_runtime_core-0.7.1/agent_runtime_core/tools.py +179 -0
- agent_runtime_core-0.7.1/agent_runtime_core/vectorstore/__init__.py +193 -0
- agent_runtime_core-0.7.1/agent_runtime_core/vectorstore/base.py +138 -0
- agent_runtime_core-0.7.1/agent_runtime_core/vectorstore/embeddings.py +242 -0
- agent_runtime_core-0.7.1/agent_runtime_core/vectorstore/sqlite_vec.py +328 -0
- agent_runtime_core-0.7.1/agent_runtime_core/vectorstore/vertex.py +295 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/pyproject.toml +6 -1
- agent_runtime_core-0.7.1/tests/test_memory.py +503 -0
- agent_runtime_core-0.7.1/tests/test_multi_agent.py +465 -0
- agent_runtime_core-0.7.1/tests/test_rag.py +235 -0
- agent_runtime_core-0.7.1/tests/test_tools.py +275 -0
- agent_runtime_core-0.7.1/tests/test_vectorstore.py +242 -0
- agent_runtime_core-0.7.0/agent_runtime_core/llm/__init__.py +0 -83
- agent_runtime_core-0.7.0/agent_runtime_core/tool_calling_agent.py +0 -256
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/.gitignore +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/LICENSE +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/contexts.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/events/__init__.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/events/base.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/events/memory.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/events/redis.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/events/sqlite.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/llm/litellm_client.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/llm/openai.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/persistence/base.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/persistence/manager.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/queue/__init__.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/queue/base.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/queue/memory.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/queue/redis.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/queue/sqlite.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/registry.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/state/__init__.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/state/base.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/state/memory.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/state/redis.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/state/sqlite.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/steps.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/testing.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/tracing/__init__.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/tracing/langfuse.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/agent_runtime_core/tracing/noop.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/tests/__init__.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/tests/test_contexts.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/tests/test_events.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/tests/test_imports.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/tests/test_persistence.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/tests/test_queue.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/tests/test_state.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/tests/test_steps.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/tests/test_testing.py +0 -0
- {agent_runtime_core-0.7.0 → agent_runtime_core-0.7.1}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-runtime-core
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.1
|
|
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,12 @@ 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: google-cloud-aiplatform>=1.38.0; extra == 'all'
|
|
22
23
|
Requires-Dist: langfuse>=2.0.0; extra == 'all'
|
|
23
24
|
Requires-Dist: litellm>=1.0.0; extra == 'all'
|
|
24
25
|
Requires-Dist: openai>=1.0.0; extra == 'all'
|
|
25
26
|
Requires-Dist: redis>=5.0.0; extra == 'all'
|
|
27
|
+
Requires-Dist: sqlite-vec>=0.1.0; extra == 'all'
|
|
26
28
|
Provides-Extra: anthropic
|
|
27
29
|
Requires-Dist: anthropic>=0.18.0; extra == 'anthropic'
|
|
28
30
|
Provides-Extra: dev
|
|
@@ -39,6 +41,10 @@ Provides-Extra: openai
|
|
|
39
41
|
Requires-Dist: openai>=1.0.0; extra == 'openai'
|
|
40
42
|
Provides-Extra: redis
|
|
41
43
|
Requires-Dist: redis>=5.0.0; extra == 'redis'
|
|
44
|
+
Provides-Extra: sqlite-vec
|
|
45
|
+
Requires-Dist: sqlite-vec>=0.1.0; extra == 'sqlite-vec'
|
|
46
|
+
Provides-Extra: vertex
|
|
47
|
+
Requires-Dist: google-cloud-aiplatform>=1.38.0; extra == 'vertex'
|
|
42
48
|
Description-Content-Type: text/markdown
|
|
43
49
|
|
|
44
50
|
# agent-runtime-core
|
|
@@ -53,6 +59,7 @@ A lightweight, framework-agnostic Python library for building AI agent systems.
|
|
|
53
59
|
|
|
54
60
|
| Version | Date | Changes |
|
|
55
61
|
|---------|------|---------|
|
|
62
|
+
| **0.7.1** | 2026-01-24 | RAG module, vector stores (sqlite-vec, Vertex AI), memory system, multi-agent support, agentic loop, JSON runtime |
|
|
56
63
|
| **0.6.0** | 2025-01-23 | Enhanced registry with factory functions and class registration |
|
|
57
64
|
| **0.5.2** | 2025-01-14 | Add ToolCallingAgent base class, execute_with_events helper |
|
|
58
65
|
| **0.5.1** | 2025-01-13 | Bug fixes and improvements |
|
|
@@ -820,6 +827,200 @@ The executor emits events for observability:
|
|
|
820
827
|
- `EventType.STEP_SKIPPED` - Step skipped (already completed)
|
|
821
828
|
- `EventType.PROGRESS_UPDATE` - Progress percentage update
|
|
822
829
|
|
|
830
|
+
## Multi-Agent Systems
|
|
831
|
+
|
|
832
|
+
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.
|
|
833
|
+
|
|
834
|
+
### Core Concepts
|
|
835
|
+
|
|
836
|
+
**Invocation Modes:**
|
|
837
|
+
- `DELEGATE`: Sub-agent runs and returns result to parent (parent continues). Good for "get me an answer".
|
|
838
|
+
- `HANDOFF`: Control transfers completely to sub-agent (parent exits). Good for "transfer this customer to billing".
|
|
839
|
+
|
|
840
|
+
**Context Modes:**
|
|
841
|
+
- `FULL`: Complete conversation history passed to sub-agent (default)
|
|
842
|
+
- `SUMMARY`: Summarized context + current message (more efficient)
|
|
843
|
+
- `MESSAGE_ONLY`: Only the invocation message (clean isolation)
|
|
844
|
+
|
|
845
|
+
### Creating Agent Tools
|
|
846
|
+
|
|
847
|
+
Wrap any agent as a tool that can be called by other agents:
|
|
848
|
+
|
|
849
|
+
```python
|
|
850
|
+
from agent_runtime_core.multi_agent import (
|
|
851
|
+
AgentTool,
|
|
852
|
+
InvocationMode,
|
|
853
|
+
ContextMode,
|
|
854
|
+
invoke_agent,
|
|
855
|
+
register_agent_tools,
|
|
856
|
+
)
|
|
857
|
+
|
|
858
|
+
# Define specialist agents
|
|
859
|
+
class BillingAgent(AgentRuntime):
|
|
860
|
+
@property
|
|
861
|
+
def key(self) -> str:
|
|
862
|
+
return "billing-specialist"
|
|
863
|
+
|
|
864
|
+
async def run(self, ctx: RunContext) -> RunResult:
|
|
865
|
+
# Handle billing questions, refunds, payments
|
|
866
|
+
...
|
|
867
|
+
|
|
868
|
+
class TechSupportAgent(AgentRuntime):
|
|
869
|
+
@property
|
|
870
|
+
def key(self) -> str:
|
|
871
|
+
return "tech-support"
|
|
872
|
+
|
|
873
|
+
async def run(self, ctx: RunContext) -> RunResult:
|
|
874
|
+
# Handle technical issues
|
|
875
|
+
...
|
|
876
|
+
|
|
877
|
+
# Wrap agents as tools
|
|
878
|
+
billing_tool = AgentTool(
|
|
879
|
+
agent=BillingAgent(),
|
|
880
|
+
name="billing_specialist",
|
|
881
|
+
description="Handles billing questions, refunds, and payment issues. Use when customer has billing-related questions.",
|
|
882
|
+
invocation_mode=InvocationMode.DELEGATE,
|
|
883
|
+
context_mode=ContextMode.FULL,
|
|
884
|
+
)
|
|
885
|
+
|
|
886
|
+
tech_support_tool = AgentTool(
|
|
887
|
+
agent=TechSupportAgent(),
|
|
888
|
+
name="tech_support",
|
|
889
|
+
description="Handles technical issues and troubleshooting. Use for technical problems.",
|
|
890
|
+
invocation_mode=InvocationMode.HANDOFF, # Transfer control completely
|
|
891
|
+
)
|
|
892
|
+
```
|
|
893
|
+
|
|
894
|
+
### Router Agent Pattern
|
|
895
|
+
|
|
896
|
+
Create a router agent that delegates to specialists:
|
|
897
|
+
|
|
898
|
+
```python
|
|
899
|
+
class RouterAgent(AgentRuntime):
|
|
900
|
+
"""Routes customer requests to appropriate specialist agents."""
|
|
901
|
+
|
|
902
|
+
def __init__(self):
|
|
903
|
+
self.agent_tools = [billing_tool, tech_support_tool]
|
|
904
|
+
|
|
905
|
+
@property
|
|
906
|
+
def key(self) -> str:
|
|
907
|
+
return "customer-router"
|
|
908
|
+
|
|
909
|
+
async def run(self, ctx: RunContext) -> RunResult:
|
|
910
|
+
from agent_runtime_core.llm import get_llm_client
|
|
911
|
+
llm = get_llm_client()
|
|
912
|
+
|
|
913
|
+
# Create tool registry with agent-tools
|
|
914
|
+
tools = ToolRegistry()
|
|
915
|
+
messages = list(ctx.input_messages)
|
|
916
|
+
|
|
917
|
+
# Register agent-tools as callable tools
|
|
918
|
+
register_agent_tools(
|
|
919
|
+
registry=tools,
|
|
920
|
+
agent_tools=self.agent_tools,
|
|
921
|
+
get_conversation_history=lambda: messages,
|
|
922
|
+
parent_ctx=ctx,
|
|
923
|
+
)
|
|
924
|
+
|
|
925
|
+
# Add system prompt for routing
|
|
926
|
+
system_message = {
|
|
927
|
+
"role": "system",
|
|
928
|
+
"content": """You are a customer service router. Analyze the customer's
|
|
929
|
+
request and delegate to the appropriate specialist:
|
|
930
|
+
- billing_specialist: For billing, payments, refunds
|
|
931
|
+
- tech_support: For technical issues (this will transfer the customer)
|
|
932
|
+
|
|
933
|
+
If you can answer directly, do so. Otherwise, use the appropriate tool."""
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
while True:
|
|
937
|
+
response = await llm.generate(
|
|
938
|
+
[system_message] + messages,
|
|
939
|
+
tools=tools.to_openai_format(),
|
|
940
|
+
)
|
|
941
|
+
|
|
942
|
+
messages.append(response.message)
|
|
943
|
+
|
|
944
|
+
if not response.tool_calls:
|
|
945
|
+
# No tool call - respond directly
|
|
946
|
+
await ctx.emit(EventType.ASSISTANT_MESSAGE, {
|
|
947
|
+
"content": response.content,
|
|
948
|
+
})
|
|
949
|
+
break
|
|
950
|
+
|
|
951
|
+
# Execute tool calls (which may invoke sub-agents)
|
|
952
|
+
for tool_call in response.tool_calls:
|
|
953
|
+
result = await tools.execute_with_events(tool_call, ctx)
|
|
954
|
+
|
|
955
|
+
# Check for handoff
|
|
956
|
+
if isinstance(result, dict) and result.get("handoff"):
|
|
957
|
+
# Sub-agent took over - we're done
|
|
958
|
+
return RunResult(
|
|
959
|
+
final_output=result.get("final_output", {}),
|
|
960
|
+
final_messages=messages,
|
|
961
|
+
)
|
|
962
|
+
|
|
963
|
+
# Add result to conversation
|
|
964
|
+
messages.append({
|
|
965
|
+
"role": "tool",
|
|
966
|
+
"tool_call_id": tool_call.id,
|
|
967
|
+
"content": str(result.get("response", result)),
|
|
968
|
+
})
|
|
969
|
+
|
|
970
|
+
return RunResult(
|
|
971
|
+
final_output={"response": response.content},
|
|
972
|
+
final_messages=messages,
|
|
973
|
+
)
|
|
974
|
+
```
|
|
975
|
+
|
|
976
|
+
### Direct Invocation
|
|
977
|
+
|
|
978
|
+
You can also invoke agents directly without the tool pattern:
|
|
979
|
+
|
|
980
|
+
```python
|
|
981
|
+
from agent_runtime_core.multi_agent import invoke_agent
|
|
982
|
+
|
|
983
|
+
# Invoke a sub-agent directly
|
|
984
|
+
result = await invoke_agent(
|
|
985
|
+
agent_tool=billing_tool,
|
|
986
|
+
message="Customer wants a refund for order #123",
|
|
987
|
+
parent_ctx=ctx,
|
|
988
|
+
conversation_history=messages,
|
|
989
|
+
additional_context="Customer has been waiting 2 weeks",
|
|
990
|
+
)
|
|
991
|
+
|
|
992
|
+
if result.handoff:
|
|
993
|
+
# Sub-agent took over
|
|
994
|
+
return RunResult(final_output=result.run_result.final_output)
|
|
995
|
+
else:
|
|
996
|
+
# Use the response
|
|
997
|
+
print(result.response)
|
|
998
|
+
```
|
|
999
|
+
|
|
1000
|
+
### Events
|
|
1001
|
+
|
|
1002
|
+
Multi-agent invocations emit events for observability:
|
|
1003
|
+
|
|
1004
|
+
- `sub_agent.start` - Sub-agent invocation started
|
|
1005
|
+
- `sub_agent.end` - Sub-agent invocation completed
|
|
1006
|
+
- `tool.call` with `is_agent_tool: true` - Agent-tool was called
|
|
1007
|
+
- `tool.result` with `is_agent_tool: true` - Agent-tool returned
|
|
1008
|
+
|
|
1009
|
+
### AgentTool Options
|
|
1010
|
+
|
|
1011
|
+
```python
|
|
1012
|
+
AgentTool(
|
|
1013
|
+
agent=my_agent, # Required: The agent to wrap
|
|
1014
|
+
name="specialist", # Required: Tool name
|
|
1015
|
+
description="When to use this agent", # Required: Shown to parent LLM
|
|
1016
|
+
invocation_mode=InvocationMode.DELEGATE, # DELEGATE or HANDOFF
|
|
1017
|
+
context_mode=ContextMode.FULL, # FULL, SUMMARY, or MESSAGE_ONLY
|
|
1018
|
+
max_turns=10, # Optional: Limit sub-agent turns
|
|
1019
|
+
input_schema={...}, # Optional: Custom input schema
|
|
1020
|
+
metadata={"category": "billing"}, # Optional: Additional metadata
|
|
1021
|
+
)
|
|
1022
|
+
```
|
|
1023
|
+
|
|
823
1024
|
## API Reference
|
|
824
1025
|
|
|
825
1026
|
### Configuration
|
|
@@ -10,6 +10,7 @@ A lightweight, framework-agnostic Python library for building AI agent systems.
|
|
|
10
10
|
|
|
11
11
|
| Version | Date | Changes |
|
|
12
12
|
|---------|------|---------|
|
|
13
|
+
| **0.7.1** | 2026-01-24 | RAG module, vector stores (sqlite-vec, Vertex AI), memory system, multi-agent support, agentic loop, JSON runtime |
|
|
13
14
|
| **0.6.0** | 2025-01-23 | Enhanced registry with factory functions and class registration |
|
|
14
15
|
| **0.5.2** | 2025-01-14 | Add ToolCallingAgent base class, execute_with_events helper |
|
|
15
16
|
| **0.5.1** | 2025-01-13 | Bug fixes and improvements |
|
|
@@ -777,6 +778,200 @@ The executor emits events for observability:
|
|
|
777
778
|
- `EventType.STEP_SKIPPED` - Step skipped (already completed)
|
|
778
779
|
- `EventType.PROGRESS_UPDATE` - Progress percentage update
|
|
779
780
|
|
|
781
|
+
## Multi-Agent Systems
|
|
782
|
+
|
|
783
|
+
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.
|
|
784
|
+
|
|
785
|
+
### Core Concepts
|
|
786
|
+
|
|
787
|
+
**Invocation Modes:**
|
|
788
|
+
- `DELEGATE`: Sub-agent runs and returns result to parent (parent continues). Good for "get me an answer".
|
|
789
|
+
- `HANDOFF`: Control transfers completely to sub-agent (parent exits). Good for "transfer this customer to billing".
|
|
790
|
+
|
|
791
|
+
**Context Modes:**
|
|
792
|
+
- `FULL`: Complete conversation history passed to sub-agent (default)
|
|
793
|
+
- `SUMMARY`: Summarized context + current message (more efficient)
|
|
794
|
+
- `MESSAGE_ONLY`: Only the invocation message (clean isolation)
|
|
795
|
+
|
|
796
|
+
### Creating Agent Tools
|
|
797
|
+
|
|
798
|
+
Wrap any agent as a tool that can be called by other agents:
|
|
799
|
+
|
|
800
|
+
```python
|
|
801
|
+
from agent_runtime_core.multi_agent import (
|
|
802
|
+
AgentTool,
|
|
803
|
+
InvocationMode,
|
|
804
|
+
ContextMode,
|
|
805
|
+
invoke_agent,
|
|
806
|
+
register_agent_tools,
|
|
807
|
+
)
|
|
808
|
+
|
|
809
|
+
# Define specialist agents
|
|
810
|
+
class BillingAgent(AgentRuntime):
|
|
811
|
+
@property
|
|
812
|
+
def key(self) -> str:
|
|
813
|
+
return "billing-specialist"
|
|
814
|
+
|
|
815
|
+
async def run(self, ctx: RunContext) -> RunResult:
|
|
816
|
+
# Handle billing questions, refunds, payments
|
|
817
|
+
...
|
|
818
|
+
|
|
819
|
+
class TechSupportAgent(AgentRuntime):
|
|
820
|
+
@property
|
|
821
|
+
def key(self) -> str:
|
|
822
|
+
return "tech-support"
|
|
823
|
+
|
|
824
|
+
async def run(self, ctx: RunContext) -> RunResult:
|
|
825
|
+
# Handle technical issues
|
|
826
|
+
...
|
|
827
|
+
|
|
828
|
+
# Wrap agents as tools
|
|
829
|
+
billing_tool = AgentTool(
|
|
830
|
+
agent=BillingAgent(),
|
|
831
|
+
name="billing_specialist",
|
|
832
|
+
description="Handles billing questions, refunds, and payment issues. Use when customer has billing-related questions.",
|
|
833
|
+
invocation_mode=InvocationMode.DELEGATE,
|
|
834
|
+
context_mode=ContextMode.FULL,
|
|
835
|
+
)
|
|
836
|
+
|
|
837
|
+
tech_support_tool = AgentTool(
|
|
838
|
+
agent=TechSupportAgent(),
|
|
839
|
+
name="tech_support",
|
|
840
|
+
description="Handles technical issues and troubleshooting. Use for technical problems.",
|
|
841
|
+
invocation_mode=InvocationMode.HANDOFF, # Transfer control completely
|
|
842
|
+
)
|
|
843
|
+
```
|
|
844
|
+
|
|
845
|
+
### Router Agent Pattern
|
|
846
|
+
|
|
847
|
+
Create a router agent that delegates to specialists:
|
|
848
|
+
|
|
849
|
+
```python
|
|
850
|
+
class RouterAgent(AgentRuntime):
|
|
851
|
+
"""Routes customer requests to appropriate specialist agents."""
|
|
852
|
+
|
|
853
|
+
def __init__(self):
|
|
854
|
+
self.agent_tools = [billing_tool, tech_support_tool]
|
|
855
|
+
|
|
856
|
+
@property
|
|
857
|
+
def key(self) -> str:
|
|
858
|
+
return "customer-router"
|
|
859
|
+
|
|
860
|
+
async def run(self, ctx: RunContext) -> RunResult:
|
|
861
|
+
from agent_runtime_core.llm import get_llm_client
|
|
862
|
+
llm = get_llm_client()
|
|
863
|
+
|
|
864
|
+
# Create tool registry with agent-tools
|
|
865
|
+
tools = ToolRegistry()
|
|
866
|
+
messages = list(ctx.input_messages)
|
|
867
|
+
|
|
868
|
+
# Register agent-tools as callable tools
|
|
869
|
+
register_agent_tools(
|
|
870
|
+
registry=tools,
|
|
871
|
+
agent_tools=self.agent_tools,
|
|
872
|
+
get_conversation_history=lambda: messages,
|
|
873
|
+
parent_ctx=ctx,
|
|
874
|
+
)
|
|
875
|
+
|
|
876
|
+
# Add system prompt for routing
|
|
877
|
+
system_message = {
|
|
878
|
+
"role": "system",
|
|
879
|
+
"content": """You are a customer service router. Analyze the customer's
|
|
880
|
+
request and delegate to the appropriate specialist:
|
|
881
|
+
- billing_specialist: For billing, payments, refunds
|
|
882
|
+
- tech_support: For technical issues (this will transfer the customer)
|
|
883
|
+
|
|
884
|
+
If you can answer directly, do so. Otherwise, use the appropriate tool."""
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
while True:
|
|
888
|
+
response = await llm.generate(
|
|
889
|
+
[system_message] + messages,
|
|
890
|
+
tools=tools.to_openai_format(),
|
|
891
|
+
)
|
|
892
|
+
|
|
893
|
+
messages.append(response.message)
|
|
894
|
+
|
|
895
|
+
if not response.tool_calls:
|
|
896
|
+
# No tool call - respond directly
|
|
897
|
+
await ctx.emit(EventType.ASSISTANT_MESSAGE, {
|
|
898
|
+
"content": response.content,
|
|
899
|
+
})
|
|
900
|
+
break
|
|
901
|
+
|
|
902
|
+
# Execute tool calls (which may invoke sub-agents)
|
|
903
|
+
for tool_call in response.tool_calls:
|
|
904
|
+
result = await tools.execute_with_events(tool_call, ctx)
|
|
905
|
+
|
|
906
|
+
# Check for handoff
|
|
907
|
+
if isinstance(result, dict) and result.get("handoff"):
|
|
908
|
+
# Sub-agent took over - we're done
|
|
909
|
+
return RunResult(
|
|
910
|
+
final_output=result.get("final_output", {}),
|
|
911
|
+
final_messages=messages,
|
|
912
|
+
)
|
|
913
|
+
|
|
914
|
+
# Add result to conversation
|
|
915
|
+
messages.append({
|
|
916
|
+
"role": "tool",
|
|
917
|
+
"tool_call_id": tool_call.id,
|
|
918
|
+
"content": str(result.get("response", result)),
|
|
919
|
+
})
|
|
920
|
+
|
|
921
|
+
return RunResult(
|
|
922
|
+
final_output={"response": response.content},
|
|
923
|
+
final_messages=messages,
|
|
924
|
+
)
|
|
925
|
+
```
|
|
926
|
+
|
|
927
|
+
### Direct Invocation
|
|
928
|
+
|
|
929
|
+
You can also invoke agents directly without the tool pattern:
|
|
930
|
+
|
|
931
|
+
```python
|
|
932
|
+
from agent_runtime_core.multi_agent import invoke_agent
|
|
933
|
+
|
|
934
|
+
# Invoke a sub-agent directly
|
|
935
|
+
result = await invoke_agent(
|
|
936
|
+
agent_tool=billing_tool,
|
|
937
|
+
message="Customer wants a refund for order #123",
|
|
938
|
+
parent_ctx=ctx,
|
|
939
|
+
conversation_history=messages,
|
|
940
|
+
additional_context="Customer has been waiting 2 weeks",
|
|
941
|
+
)
|
|
942
|
+
|
|
943
|
+
if result.handoff:
|
|
944
|
+
# Sub-agent took over
|
|
945
|
+
return RunResult(final_output=result.run_result.final_output)
|
|
946
|
+
else:
|
|
947
|
+
# Use the response
|
|
948
|
+
print(result.response)
|
|
949
|
+
```
|
|
950
|
+
|
|
951
|
+
### Events
|
|
952
|
+
|
|
953
|
+
Multi-agent invocations emit events for observability:
|
|
954
|
+
|
|
955
|
+
- `sub_agent.start` - Sub-agent invocation started
|
|
956
|
+
- `sub_agent.end` - Sub-agent invocation completed
|
|
957
|
+
- `tool.call` with `is_agent_tool: true` - Agent-tool was called
|
|
958
|
+
- `tool.result` with `is_agent_tool: true` - Agent-tool returned
|
|
959
|
+
|
|
960
|
+
### AgentTool Options
|
|
961
|
+
|
|
962
|
+
```python
|
|
963
|
+
AgentTool(
|
|
964
|
+
agent=my_agent, # Required: The agent to wrap
|
|
965
|
+
name="specialist", # Required: Tool name
|
|
966
|
+
description="When to use this agent", # Required: Shown to parent LLM
|
|
967
|
+
invocation_mode=InvocationMode.DELEGATE, # DELEGATE or HANDOFF
|
|
968
|
+
context_mode=ContextMode.FULL, # FULL, SUMMARY, or MESSAGE_ONLY
|
|
969
|
+
max_turns=10, # Optional: Limit sub-agent turns
|
|
970
|
+
input_schema={...}, # Optional: Custom input schema
|
|
971
|
+
metadata={"category": "billing"}, # Optional: Additional metadata
|
|
972
|
+
)
|
|
973
|
+
```
|
|
974
|
+
|
|
780
975
|
## API Reference
|
|
781
976
|
|
|
782
977
|
### Configuration
|
|
@@ -40,10 +40,12 @@ __version__ = "0.7.0"
|
|
|
40
40
|
from agent_runtime_core.interfaces import (
|
|
41
41
|
AgentRuntime,
|
|
42
42
|
EventType,
|
|
43
|
+
EventVisibility,
|
|
43
44
|
ErrorInfo,
|
|
44
45
|
LLMClient,
|
|
45
46
|
LLMResponse,
|
|
46
47
|
LLMStreamChunk,
|
|
48
|
+
LLMToolCall,
|
|
47
49
|
Message,
|
|
48
50
|
RunContext,
|
|
49
51
|
RunResult,
|
|
@@ -57,6 +59,12 @@ from agent_runtime_core.interfaces import (
|
|
|
57
59
|
# Tool Calling Agent base class
|
|
58
60
|
from agent_runtime_core.tool_calling_agent import ToolCallingAgent
|
|
59
61
|
|
|
62
|
+
# Agentic loop helper
|
|
63
|
+
from agent_runtime_core.agentic_loop import (
|
|
64
|
+
run_agentic_loop,
|
|
65
|
+
AgenticLoopResult,
|
|
66
|
+
)
|
|
67
|
+
|
|
60
68
|
# Configuration
|
|
61
69
|
from agent_runtime_core.config import (
|
|
62
70
|
RuntimeConfig,
|
|
@@ -128,6 +136,7 @@ from agent_runtime_core.persistence import (
|
|
|
128
136
|
FileConversationStore,
|
|
129
137
|
FileTaskStore,
|
|
130
138
|
FilePreferencesStore,
|
|
139
|
+
FileKnowledgeStore,
|
|
131
140
|
# Manager
|
|
132
141
|
PersistenceManager,
|
|
133
142
|
PersistenceConfig,
|
|
@@ -135,6 +144,69 @@ from agent_runtime_core.persistence import (
|
|
|
135
144
|
configure_persistence,
|
|
136
145
|
)
|
|
137
146
|
|
|
147
|
+
# Agent configuration schema (portable JSON format)
|
|
148
|
+
from agent_runtime_core.config_schema import (
|
|
149
|
+
AgentConfig,
|
|
150
|
+
ToolConfig,
|
|
151
|
+
KnowledgeConfig,
|
|
152
|
+
SubAgentToolConfig,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# JSON-based runtime (loads from AgentConfig)
|
|
156
|
+
from agent_runtime_core.json_runtime import (
|
|
157
|
+
JsonAgentRuntime,
|
|
158
|
+
ConfiguredTool,
|
|
159
|
+
SubAgentTool,
|
|
160
|
+
resolve_function,
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
# Vector store (optional - requires additional dependencies)
|
|
164
|
+
# Import these directly from agent_runtime_core.vectorstore when needed:
|
|
165
|
+
# from agent_runtime_core.vectorstore import (
|
|
166
|
+
# VectorStore, VectorRecord, VectorSearchResult,
|
|
167
|
+
# EmbeddingClient, OpenAIEmbeddings, VertexAIEmbeddings,
|
|
168
|
+
# get_vector_store, get_embedding_client,
|
|
169
|
+
# )
|
|
170
|
+
|
|
171
|
+
# RAG (Retrieval Augmented Generation)
|
|
172
|
+
from agent_runtime_core.rag import (
|
|
173
|
+
chunk_text,
|
|
174
|
+
ChunkingConfig,
|
|
175
|
+
TextChunk,
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
# RAG services are imported lazily to avoid circular dependencies
|
|
179
|
+
# Import directly when needed:
|
|
180
|
+
# from agent_runtime_core.rag import KnowledgeIndexer, KnowledgeRetriever
|
|
181
|
+
|
|
182
|
+
# Tool schema builder utilities
|
|
183
|
+
from agent_runtime_core.tools import (
|
|
184
|
+
ToolSchema,
|
|
185
|
+
ToolSchemaBuilder,
|
|
186
|
+
ToolParameter,
|
|
187
|
+
schemas_to_openai_format,
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
# Multi-agent support (agent-as-tool pattern)
|
|
191
|
+
from agent_runtime_core.multi_agent import (
|
|
192
|
+
AgentTool,
|
|
193
|
+
AgentInvocationResult,
|
|
194
|
+
InvocationMode,
|
|
195
|
+
ContextMode,
|
|
196
|
+
SubAgentContext,
|
|
197
|
+
invoke_agent,
|
|
198
|
+
create_agent_tool_handler,
|
|
199
|
+
register_agent_tools,
|
|
200
|
+
build_sub_agent_messages,
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
# Cross-conversation memory
|
|
204
|
+
# Import directly when needed for full functionality:
|
|
205
|
+
# from agent_runtime_core.memory import (
|
|
206
|
+
# MemoryManager, MemoryConfig, MemoryEnabledAgent,
|
|
207
|
+
# ExtractedMemory, RecalledMemory, with_memory,
|
|
208
|
+
# )
|
|
209
|
+
|
|
138
210
|
__all__ = [
|
|
139
211
|
# Version
|
|
140
212
|
"__version__",
|
|
@@ -143,6 +215,7 @@ __all__ = [
|
|
|
143
215
|
"LLMClient",
|
|
144
216
|
"LLMResponse",
|
|
145
217
|
"LLMStreamChunk",
|
|
218
|
+
"LLMToolCall",
|
|
146
219
|
"Message",
|
|
147
220
|
"RunContext",
|
|
148
221
|
"RunResult",
|
|
@@ -151,8 +224,12 @@ __all__ = [
|
|
|
151
224
|
"ToolDefinition",
|
|
152
225
|
"TraceSink",
|
|
153
226
|
"EventType",
|
|
227
|
+
"EventVisibility",
|
|
154
228
|
"ErrorInfo",
|
|
155
|
-
|
|
229
|
+
# Tool calling
|
|
230
|
+
"ToolCallingAgent",
|
|
231
|
+
"run_agentic_loop",
|
|
232
|
+
"AgenticLoopResult",
|
|
156
233
|
# Configuration
|
|
157
234
|
"RuntimeConfig",
|
|
158
235
|
"configure",
|
|
@@ -204,9 +281,39 @@ __all__ = [
|
|
|
204
281
|
"FileConversationStore",
|
|
205
282
|
"FileTaskStore",
|
|
206
283
|
"FilePreferencesStore",
|
|
284
|
+
"FileKnowledgeStore",
|
|
207
285
|
# Persistence - Manager
|
|
208
286
|
"PersistenceManager",
|
|
209
287
|
"PersistenceConfig",
|
|
210
288
|
"get_persistence_manager",
|
|
211
289
|
"configure_persistence",
|
|
290
|
+
# Agent configuration schema
|
|
291
|
+
"AgentConfig",
|
|
292
|
+
"ToolConfig",
|
|
293
|
+
"KnowledgeConfig",
|
|
294
|
+
"SubAgentToolConfig",
|
|
295
|
+
# JSON-based runtime
|
|
296
|
+
"JsonAgentRuntime",
|
|
297
|
+
"ConfiguredTool",
|
|
298
|
+
"SubAgentTool",
|
|
299
|
+
"resolve_function",
|
|
300
|
+
# RAG (Retrieval Augmented Generation)
|
|
301
|
+
"chunk_text",
|
|
302
|
+
"ChunkingConfig",
|
|
303
|
+
"TextChunk",
|
|
304
|
+
# Tool schema builder
|
|
305
|
+
"ToolSchema",
|
|
306
|
+
"ToolSchemaBuilder",
|
|
307
|
+
"ToolParameter",
|
|
308
|
+
"schemas_to_openai_format",
|
|
309
|
+
# Multi-agent support
|
|
310
|
+
"AgentTool",
|
|
311
|
+
"AgentInvocationResult",
|
|
312
|
+
"InvocationMode",
|
|
313
|
+
"ContextMode",
|
|
314
|
+
"SubAgentContext",
|
|
315
|
+
"invoke_agent",
|
|
316
|
+
"create_agent_tool_handler",
|
|
317
|
+
"register_agent_tools",
|
|
318
|
+
"build_sub_agent_messages",
|
|
212
319
|
]
|