aip-agents-binary 0.5.21__py3-none-macosx_13_0_arm64.whl → 0.6.8__py3-none-macosx_13_0_arm64.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.
- aip_agents/agent/__init__.py +44 -4
- aip_agents/agent/base_langgraph_agent.py +169 -74
- aip_agents/agent/base_langgraph_agent.pyi +3 -2
- aip_agents/agent/langgraph_memory_enhancer_agent.py +368 -34
- aip_agents/agent/langgraph_memory_enhancer_agent.pyi +3 -2
- aip_agents/agent/langgraph_react_agent.py +424 -35
- aip_agents/agent/langgraph_react_agent.pyi +46 -2
- aip_agents/examples/{hello_world_langgraph_bosa_twitter.py → hello_world_langgraph_gl_connector_twitter.py} +10 -7
- aip_agents/examples/hello_world_langgraph_gl_connector_twitter.pyi +5 -0
- aip_agents/examples/hello_world_ptc.py +49 -0
- aip_agents/examples/hello_world_ptc.pyi +5 -0
- aip_agents/examples/hello_world_ptc_custom_tools.py +83 -0
- aip_agents/examples/hello_world_ptc_custom_tools.pyi +7 -0
- aip_agents/examples/hello_world_sentry.py +2 -2
- aip_agents/examples/hello_world_tool_output_client.py +9 -0
- aip_agents/examples/tools/multiply_tool.py +43 -0
- aip_agents/examples/tools/multiply_tool.pyi +18 -0
- aip_agents/guardrails/__init__.py +83 -0
- aip_agents/guardrails/__init__.pyi +6 -0
- aip_agents/guardrails/engines/__init__.py +69 -0
- aip_agents/guardrails/engines/__init__.pyi +4 -0
- aip_agents/guardrails/engines/base.py +90 -0
- aip_agents/guardrails/engines/base.pyi +61 -0
- aip_agents/guardrails/engines/nemo.py +101 -0
- aip_agents/guardrails/engines/nemo.pyi +46 -0
- aip_agents/guardrails/engines/phrase_matcher.py +113 -0
- aip_agents/guardrails/engines/phrase_matcher.pyi +48 -0
- aip_agents/guardrails/exceptions.py +39 -0
- aip_agents/guardrails/exceptions.pyi +23 -0
- aip_agents/guardrails/manager.py +163 -0
- aip_agents/guardrails/manager.pyi +42 -0
- aip_agents/guardrails/middleware.py +199 -0
- aip_agents/guardrails/middleware.pyi +87 -0
- aip_agents/guardrails/schemas.py +63 -0
- aip_agents/guardrails/schemas.pyi +43 -0
- aip_agents/guardrails/utils.py +45 -0
- aip_agents/guardrails/utils.pyi +19 -0
- aip_agents/mcp/client/__init__.py +38 -2
- aip_agents/mcp/client/connection_manager.py +36 -1
- aip_agents/mcp/client/connection_manager.pyi +3 -0
- aip_agents/mcp/client/persistent_session.py +318 -65
- aip_agents/mcp/client/persistent_session.pyi +9 -0
- aip_agents/mcp/client/transports.py +52 -4
- aip_agents/mcp/client/transports.pyi +9 -0
- aip_agents/memory/adapters/base_adapter.py +98 -0
- aip_agents/memory/adapters/base_adapter.pyi +25 -0
- aip_agents/middleware/base.py +8 -0
- aip_agents/middleware/base.pyi +4 -0
- aip_agents/middleware/manager.py +22 -0
- aip_agents/middleware/manager.pyi +4 -0
- aip_agents/ptc/__init__.py +87 -0
- aip_agents/ptc/__init__.pyi +14 -0
- aip_agents/ptc/custom_tools.py +473 -0
- aip_agents/ptc/custom_tools.pyi +184 -0
- aip_agents/ptc/custom_tools_payload.py +400 -0
- aip_agents/ptc/custom_tools_payload.pyi +31 -0
- aip_agents/ptc/custom_tools_templates/__init__.py +1 -0
- aip_agents/ptc/custom_tools_templates/__init__.pyi +0 -0
- aip_agents/ptc/custom_tools_templates/custom_build_function.py.template +23 -0
- aip_agents/ptc/custom_tools_templates/custom_init.py.template +15 -0
- aip_agents/ptc/custom_tools_templates/custom_invoke.py.template +60 -0
- aip_agents/ptc/custom_tools_templates/custom_registry.py.template +87 -0
- aip_agents/ptc/custom_tools_templates/custom_sources_init.py.template +7 -0
- aip_agents/ptc/custom_tools_templates/custom_wrapper.py.template +19 -0
- aip_agents/ptc/doc_gen.py +122 -0
- aip_agents/ptc/doc_gen.pyi +40 -0
- aip_agents/ptc/exceptions.py +57 -0
- aip_agents/ptc/exceptions.pyi +37 -0
- aip_agents/ptc/executor.py +261 -0
- aip_agents/ptc/executor.pyi +99 -0
- aip_agents/ptc/mcp/__init__.py +45 -0
- aip_agents/ptc/mcp/__init__.pyi +7 -0
- aip_agents/ptc/mcp/sandbox_bridge.py +668 -0
- aip_agents/ptc/mcp/sandbox_bridge.pyi +47 -0
- aip_agents/ptc/mcp/templates/__init__.py +1 -0
- aip_agents/ptc/mcp/templates/__init__.pyi +0 -0
- aip_agents/ptc/mcp/templates/mcp_client.py.template +239 -0
- aip_agents/ptc/naming.py +196 -0
- aip_agents/ptc/naming.pyi +85 -0
- aip_agents/ptc/payload.py +26 -0
- aip_agents/ptc/payload.pyi +15 -0
- aip_agents/ptc/prompt_builder.py +673 -0
- aip_agents/ptc/prompt_builder.pyi +59 -0
- aip_agents/ptc/ptc_helper.py +16 -0
- aip_agents/ptc/ptc_helper.pyi +1 -0
- aip_agents/ptc/sandbox_bridge.py +256 -0
- aip_agents/ptc/sandbox_bridge.pyi +38 -0
- aip_agents/ptc/template_utils.py +33 -0
- aip_agents/ptc/template_utils.pyi +13 -0
- aip_agents/ptc/templates/__init__.py +1 -0
- aip_agents/ptc/templates/__init__.pyi +0 -0
- aip_agents/ptc/templates/ptc_helper.py.template +134 -0
- aip_agents/ptc/tool_def_helpers.py +101 -0
- aip_agents/ptc/tool_def_helpers.pyi +38 -0
- aip_agents/ptc/tool_enrichment.py +163 -0
- aip_agents/ptc/tool_enrichment.pyi +60 -0
- aip_agents/sandbox/__init__.py +43 -0
- aip_agents/sandbox/__init__.pyi +5 -0
- aip_agents/sandbox/defaults.py +205 -0
- aip_agents/sandbox/defaults.pyi +30 -0
- aip_agents/sandbox/e2b_runtime.py +295 -0
- aip_agents/sandbox/e2b_runtime.pyi +57 -0
- aip_agents/sandbox/template_builder.py +131 -0
- aip_agents/sandbox/template_builder.pyi +36 -0
- aip_agents/sandbox/types.py +24 -0
- aip_agents/sandbox/types.pyi +14 -0
- aip_agents/sandbox/validation.py +50 -0
- aip_agents/sandbox/validation.pyi +20 -0
- aip_agents/sentry/__init__.py +1 -1
- aip_agents/sentry/sentry.py +33 -12
- aip_agents/sentry/sentry.pyi +5 -4
- aip_agents/tools/__init__.py +20 -3
- aip_agents/tools/__init__.pyi +4 -2
- aip_agents/tools/browser_use/browser_use_tool.py +8 -0
- aip_agents/tools/browser_use/streaming.py +2 -0
- aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.py +80 -31
- aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.pyi +25 -9
- aip_agents/tools/code_sandbox/e2b_sandbox_tool.py +6 -6
- aip_agents/tools/constants.py +24 -12
- aip_agents/tools/constants.pyi +14 -11
- aip_agents/tools/date_range_tool.py +554 -0
- aip_agents/tools/date_range_tool.pyi +21 -0
- aip_agents/tools/execute_ptc_code.py +357 -0
- aip_agents/tools/execute_ptc_code.pyi +90 -0
- aip_agents/tools/gl_connector/__init__.py +1 -1
- aip_agents/tools/gl_connector/tool.py +62 -30
- aip_agents/tools/gl_connector/tool.pyi +3 -3
- aip_agents/tools/gl_connector_tools.py +119 -0
- aip_agents/tools/gl_connector_tools.pyi +39 -0
- aip_agents/tools/memory_search/__init__.py +8 -1
- aip_agents/tools/memory_search/__init__.pyi +3 -3
- aip_agents/tools/memory_search/mem0.py +114 -1
- aip_agents/tools/memory_search/mem0.pyi +11 -1
- aip_agents/tools/memory_search/schema.py +33 -0
- aip_agents/tools/memory_search/schema.pyi +10 -0
- aip_agents/tools/memory_search_tool.py +8 -0
- aip_agents/tools/memory_search_tool.pyi +2 -2
- aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.py +26 -1
- aip_agents/utils/langgraph/tool_output_management.py +80 -0
- aip_agents/utils/langgraph/tool_output_management.pyi +37 -0
- {aip_agents_binary-0.5.21.dist-info → aip_agents_binary-0.6.8.dist-info}/METADATA +14 -22
- {aip_agents_binary-0.5.21.dist-info → aip_agents_binary-0.6.8.dist-info}/RECORD +144 -58
- {aip_agents_binary-0.5.21.dist-info → aip_agents_binary-0.6.8.dist-info}/WHEEL +1 -1
- aip_agents/examples/demo_memory_recall.py +0 -401
- aip_agents/examples/demo_memory_recall.pyi +0 -58
- aip_agents/examples/hello_world_langgraph_bosa_twitter.pyi +0 -5
- aip_agents/tools/bosa_tools.py +0 -105
- aip_agents/tools/bosa_tools.pyi +0 -37
- {aip_agents_binary-0.5.21.dist-info → aip_agents_binary-0.6.8.dist-info}/top_level.txt +0 -0
|
@@ -2,14 +2,16 @@ from _typeshed import Incomplete
|
|
|
2
2
|
from aip_agents.agent.base_langgraph_agent import BaseLangGraphAgent as BaseLangGraphAgent
|
|
3
3
|
from aip_agents.agent.hitl.langgraph_hitl_mixin import LangGraphHitLMixin as LangGraphHitLMixin
|
|
4
4
|
from aip_agents.agent.hitl.manager import TOOL_EXECUTION_BLOCKING_DECISIONS as TOOL_EXECUTION_BLOCKING_DECISIONS
|
|
5
|
+
from aip_agents.guardrails.manager import GuardrailManager as GuardrailManager
|
|
5
6
|
from aip_agents.middleware.base import AgentMiddleware as AgentMiddleware, ModelRequest as ModelRequest
|
|
6
7
|
from aip_agents.middleware.manager import MiddlewareManager as MiddlewareManager
|
|
7
8
|
from aip_agents.middleware.todolist import TodoList as TodoList, TodoListMiddleware as TodoListMiddleware
|
|
9
|
+
from aip_agents.ptc import PTCSandboxConfig as PTCSandboxConfig
|
|
8
10
|
from aip_agents.schema.a2a import A2AStreamEventType as A2AStreamEventType
|
|
9
11
|
from aip_agents.schema.hitl import ApprovalDecision as ApprovalDecision, HitlMetadata as HitlMetadata
|
|
10
12
|
from aip_agents.schema.langgraph import ToolCallResult as ToolCallResult, ToolStorageParams as ToolStorageParams
|
|
11
13
|
from aip_agents.schema.step_limit import MaxStepsExceededError as MaxStepsExceededError, StepLimitConfig as StepLimitConfig
|
|
12
|
-
from aip_agents.tools.memory_search_tool import MEMORY_SEARCH_TOOL_NAME as MEMORY_SEARCH_TOOL_NAME
|
|
14
|
+
from aip_agents.tools.memory_search_tool import MEMORY_DELETE_TOOL_NAME as MEMORY_DELETE_TOOL_NAME, MEMORY_SEARCH_TOOL_NAME as MEMORY_SEARCH_TOOL_NAME
|
|
13
15
|
from aip_agents.tools.tool_config_injector import TOOL_CONFIGS_KEY as TOOL_CONFIGS_KEY
|
|
14
16
|
from aip_agents.utils import add_references_chunks as add_references_chunks
|
|
15
17
|
from aip_agents.utils.langgraph import convert_langchain_messages_to_gllm_messages as convert_langchain_messages_to_gllm_messages, convert_lm_output_to_langchain_message as convert_lm_output_to_langchain_message
|
|
@@ -85,7 +87,7 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
85
87
|
"""
|
|
86
88
|
tool_output_manager: Incomplete
|
|
87
89
|
step_limit_config: Incomplete
|
|
88
|
-
def __init__(self, name: str, instruction: str = ..., model: BaseChatModel | str | Any | None = None, tools: Sequence[BaseTool] | None = None, agents: Sequence[Any] | None = None, description: str | None = None, thread_id_key: str = 'thread_id', event_emitter: EventEmitter | None = None, tool_output_manager: ToolOutputManager | None = None, planning: bool = False, middlewares: Sequence[AgentMiddleware] | None = None, step_limit_config: StepLimitConfig | None = None, **kwargs: Any) -> None:
|
|
90
|
+
def __init__(self, name: str, instruction: str = ..., model: BaseChatModel | str | Any | None = None, tools: Sequence[BaseTool] | None = None, agents: Sequence[Any] | None = None, description: str | None = None, thread_id_key: str = 'thread_id', event_emitter: EventEmitter | None = None, tool_output_manager: ToolOutputManager | None = None, planning: bool = False, middlewares: Sequence[AgentMiddleware] | None = None, guardrail: GuardrailManager | None = None, step_limit_config: StepLimitConfig | None = None, ptc_config: PTCSandboxConfig | None = None, **kwargs: Any) -> None:
|
|
89
91
|
"""Initialize the LangGraph ReAct Agent.
|
|
90
92
|
|
|
91
93
|
Args:
|
|
@@ -104,10 +106,19 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
104
106
|
planning: Enable planning capabilities with TodoListMiddleware. Defaults to False.
|
|
105
107
|
middlewares: Optional sequence of custom middleware to COMPOSE (not override) with built-in middleware.
|
|
106
108
|
Execution order: [TodoListMiddleware (if planning=True),
|
|
109
|
+
GuardrailMiddleware (if guardrail provided),
|
|
107
110
|
...custom middlewares in order provided]
|
|
108
111
|
All middleware hooks execute - this extends capabilities, never replaces them.
|
|
112
|
+
guardrail: Optional GuardrailManager for content filtering and safety checks.
|
|
113
|
+
When provided, automatically wraps in GuardrailMiddleware for transparent
|
|
114
|
+
input/output filtering during agent execution.
|
|
109
115
|
enable_pii: Optional toggle to enable PII handling for tool inputs and outputs.
|
|
110
116
|
step_limit_config: Optional configuration for step limits and delegation depth.
|
|
117
|
+
ptc_config: Optional configuration for PTC sandbox execution. See PTCSandboxConfig
|
|
118
|
+
for available options including enabled flag, sandbox timeout, and template settings.
|
|
119
|
+
PTC is enabled when ptc_config is not None and ptc_config.enabled is True.
|
|
120
|
+
When enabled, prompt guidance is automatically injected into the agent's instruction.
|
|
121
|
+
PTC runs in a sandbox only; there is no in-process trusted PTC path.
|
|
111
122
|
**kwargs: Additional keyword arguments passed to BaseLangGraphAgent.
|
|
112
123
|
"""
|
|
113
124
|
def define_graph(self, graph_builder: StateGraph) -> CompiledStateGraph:
|
|
@@ -119,6 +130,39 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
119
130
|
Returns:
|
|
120
131
|
Compiled LangGraph ready for execution.
|
|
121
132
|
"""
|
|
133
|
+
def add_mcp_server(self, mcp_config: dict[str, dict[str, Any]]) -> None:
|
|
134
|
+
"""Add MCP servers and refresh PTC tool state if needed."""
|
|
135
|
+
def enable_ptc(self, config: PTCSandboxConfig | None = None) -> None:
|
|
136
|
+
'''Enable Programmatic Tool Calling (PTC) for this agent.
|
|
137
|
+
|
|
138
|
+
PTC allows the LLM to execute Python code that calls MCP tools
|
|
139
|
+
programmatically inside a sandboxed environment. This is useful for
|
|
140
|
+
chaining multiple tool calls with local data processing.
|
|
141
|
+
|
|
142
|
+
The execute_ptc_code tool is automatically added to the agent\'s tools
|
|
143
|
+
after MCP servers are configured. If no MCP servers are configured,
|
|
144
|
+
the tool sync is deferred until servers are added.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
config: Optional configuration for PTC sandbox execution.
|
|
148
|
+
See PTCSandboxConfig for options like enabled flag and sandbox_timeout.
|
|
149
|
+
If None is passed, a default config with enabled=True will be created.
|
|
150
|
+
|
|
151
|
+
Example:
|
|
152
|
+
agent.enable_ptc(PTCSandboxConfig(enabled=True))
|
|
153
|
+
agent.add_mcp_server({"yfinance": {...}})
|
|
154
|
+
# execute_ptc_code tool is now available
|
|
155
|
+
|
|
156
|
+
Note:
|
|
157
|
+
PTC can also be enabled via the constructor by passing
|
|
158
|
+
ptc_config=PTCSandboxConfig(enabled=True, ...).
|
|
159
|
+
'''
|
|
160
|
+
async def cleanup(self) -> None:
|
|
161
|
+
"""Cleanup agent resources including PTC sandbox.
|
|
162
|
+
|
|
163
|
+
Extends base cleanup to also cleanup the PTC sandbox runtime if
|
|
164
|
+
execute_ptc_code tool was created.
|
|
165
|
+
"""
|
|
122
166
|
|
|
123
167
|
class LangGraphAgent(LangGraphReactAgent):
|
|
124
168
|
"""Alias for LangGraphReactAgent."""
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Minimal LangGraph agent with
|
|
1
|
+
"""Minimal LangGraph agent with GL Connectors support example demonstrating asynchronous run.
|
|
2
2
|
|
|
3
3
|
Authors:
|
|
4
4
|
Saul Sayers (saul.sayers@gdplabs.id)
|
|
@@ -6,22 +6,25 @@ Authors:
|
|
|
6
6
|
|
|
7
7
|
import asyncio
|
|
8
8
|
|
|
9
|
+
from dotenv import load_dotenv
|
|
9
10
|
from langchain_openai import ChatOpenAI
|
|
10
11
|
|
|
11
12
|
from aip_agents.agent import LangGraphAgent
|
|
12
|
-
from aip_agents.tools import
|
|
13
|
+
from aip_agents.tools import GL_CONNECTORS_AUTOMATED_TOOLS
|
|
13
14
|
|
|
15
|
+
load_dotenv(override=True)
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
|
|
18
|
+
async def langgraph_gl_connector_example():
|
|
16
19
|
"""Demonstrates the LangGraphAgent's arun method."""
|
|
17
20
|
model = ChatOpenAI(model="gpt-4.1", temperature=0)
|
|
18
|
-
agent_name = "
|
|
21
|
+
agent_name = "GLConnectorTwitterAgent"
|
|
19
22
|
|
|
20
23
|
langgraph_agent = LangGraphAgent(
|
|
21
24
|
name=agent_name,
|
|
22
|
-
instruction="You are a helpful assistant that
|
|
25
|
+
instruction="You are a helpful assistant that uses GL Connectors to connect with the Twitter API.",
|
|
23
26
|
model=model,
|
|
24
|
-
tools=
|
|
27
|
+
tools=GL_CONNECTORS_AUTOMATED_TOOLS["twitter"],
|
|
25
28
|
)
|
|
26
29
|
|
|
27
30
|
query = "Get 3 tweets about the latest Air India Incident"
|
|
@@ -38,4 +41,4 @@ async def langgraph_bosa_example():
|
|
|
38
41
|
|
|
39
42
|
|
|
40
43
|
if __name__ == "__main__":
|
|
41
|
-
asyncio.run(
|
|
44
|
+
asyncio.run(langgraph_gl_connector_example())
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Minimal PTC hello world example.
|
|
2
|
+
|
|
3
|
+
Required environment variables:
|
|
4
|
+
- OPENAI_API_KEY
|
|
5
|
+
- E2B_API_KEY
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import asyncio
|
|
9
|
+
|
|
10
|
+
from aip_agents.agent import LangGraphReactAgent
|
|
11
|
+
from aip_agents.ptc import PromptConfig, PTCSandboxConfig
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
async def main() -> None:
|
|
15
|
+
"""Run a hello-world PTC flow."""
|
|
16
|
+
instruction = (
|
|
17
|
+
"You are a helpful assistant with access to execute_ptc_code. "
|
|
18
|
+
"Use execute_ptc_code to run Python and print output. "
|
|
19
|
+
"The tool returns JSON with ok/stdout/stderr/exit_code."
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
agent = LangGraphReactAgent(
|
|
23
|
+
name="ptc_hello_world",
|
|
24
|
+
instruction=instruction,
|
|
25
|
+
model="openai/gpt-5.2",
|
|
26
|
+
ptc_config=PTCSandboxConfig(enabled=True, sandbox_timeout=180.0, prompt=PromptConfig(mode="index")),
|
|
27
|
+
)
|
|
28
|
+
agent.add_mcp_server(
|
|
29
|
+
{
|
|
30
|
+
"deepwiki": {
|
|
31
|
+
"transport": "streamable-http",
|
|
32
|
+
"url": "https://mcp.deepwiki.com/mcp",
|
|
33
|
+
"headers": {},
|
|
34
|
+
"timeout": 60.0,
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
response = await agent.arun(
|
|
41
|
+
query="Use execute_ptc_code to print 'Hello, world!' and count the number of words in the output of deepwiki.read_wiki_structure('anthropics/claude-code')."
|
|
42
|
+
)
|
|
43
|
+
print("execute_ptc_code output:", response["output"])
|
|
44
|
+
finally:
|
|
45
|
+
await agent.cleanup()
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
if __name__ == "__main__":
|
|
49
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""Minimal PTC hello world example with custom tools.
|
|
2
|
+
|
|
3
|
+
Author: Putu Ravindra Wiguna (putu.r.wiguna@gdplabs.id)
|
|
4
|
+
|
|
5
|
+
Required environment variables:
|
|
6
|
+
- OPENAI_API_KEY
|
|
7
|
+
- E2B_API_KEY
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import asyncio
|
|
11
|
+
import json
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
from langchain_openai import ChatOpenAI
|
|
15
|
+
|
|
16
|
+
from aip_agents.agent import LangGraphReactAgent
|
|
17
|
+
from aip_agents.examples.tools.multiply_tool import MultiplyTool
|
|
18
|
+
from aip_agents.ptc import PromptConfig, PTCCustomToolConfig, PTCSandboxConfig, file_tool, package_tool
|
|
19
|
+
from aip_agents.tools.time_tool import TimeTool
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
async def main() -> None:
|
|
23
|
+
"""Run a hello-world PTC flow with custom tools."""
|
|
24
|
+
repo_root = Path.cwd()
|
|
25
|
+
multiply_tool_path = repo_root / "aip_agents/examples/tools/multiply_tool.py"
|
|
26
|
+
|
|
27
|
+
instruction = (
|
|
28
|
+
"You are a helpful assistant with access to execute_ptc_code. "
|
|
29
|
+
"Use execute_ptc_code to run Python and print output. "
|
|
30
|
+
"Custom tools are available under tools.custom (import with "
|
|
31
|
+
"'from tools.custom import <tool_name>')."
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
agent = LangGraphReactAgent(
|
|
35
|
+
name="ptc_custom_tools_hello_world",
|
|
36
|
+
instruction=instruction,
|
|
37
|
+
model=ChatOpenAI(model="gpt-5.2"),
|
|
38
|
+
tools=[TimeTool(), MultiplyTool()],
|
|
39
|
+
tool_configs={"multiply": {"offset": 20}},
|
|
40
|
+
ptc_config=PTCSandboxConfig(
|
|
41
|
+
enabled=True,
|
|
42
|
+
sandbox_timeout=180.0,
|
|
43
|
+
prompt=PromptConfig(mode="auto"),
|
|
44
|
+
custom_tools=PTCCustomToolConfig(
|
|
45
|
+
enabled=True,
|
|
46
|
+
bundle_roots=[str(repo_root)],
|
|
47
|
+
requirements=[],
|
|
48
|
+
tools=[
|
|
49
|
+
package_tool(
|
|
50
|
+
"time_tool",
|
|
51
|
+
import_path="aip_agents.tools.time_tool",
|
|
52
|
+
class_name="TimeTool",
|
|
53
|
+
),
|
|
54
|
+
file_tool(
|
|
55
|
+
"multiply",
|
|
56
|
+
file_path=str(multiply_tool_path),
|
|
57
|
+
class_name="MultiplyTool",
|
|
58
|
+
),
|
|
59
|
+
],
|
|
60
|
+
),
|
|
61
|
+
),
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
try:
|
|
65
|
+
# Pass tool config at runtime via metadata
|
|
66
|
+
# The multiply tool will use offset=10, so multiply(a=6, b=7) returns 6*7+10=52
|
|
67
|
+
print("execute_ptc_code output: ", end="")
|
|
68
|
+
last_chunk = None
|
|
69
|
+
async for chunk in agent.arun_sse_stream(
|
|
70
|
+
query=("Use execute_ptc_code to import from tools.custom. Print time_tool() and multiply(a=6, b=7)."),
|
|
71
|
+
metadata={"tool_configs": {"multiply": {"offset": 10}}},
|
|
72
|
+
):
|
|
73
|
+
last_chunk = chunk
|
|
74
|
+
print(json.dumps(chunk))
|
|
75
|
+
print("-" * 20)
|
|
76
|
+
finally:
|
|
77
|
+
await agent.cleanup()
|
|
78
|
+
|
|
79
|
+
print("execute_ptc_code output: ", last_chunk["content"])
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
if __name__ == "__main__":
|
|
83
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
from aip_agents.agent import LangGraphReactAgent as LangGraphReactAgent
|
|
2
|
+
from aip_agents.examples.tools.multiply_tool import MultiplyTool as MultiplyTool
|
|
3
|
+
from aip_agents.ptc import PTCCustomToolConfig as PTCCustomToolConfig, PTCSandboxConfig as PTCSandboxConfig, PromptConfig as PromptConfig, file_tool as file_tool, package_tool as package_tool
|
|
4
|
+
from aip_agents.tools.time_tool import TimeTool as TimeTool
|
|
5
|
+
|
|
6
|
+
async def main() -> None:
|
|
7
|
+
"""Run a hello-world PTC flow with custom tools."""
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""This is a simple FastAPI app to test Sentry with Open Telemetry from
|
|
1
|
+
"""This is a simple FastAPI app to test Sentry with Open Telemetry from GL Connectors SDK.
|
|
2
2
|
|
|
3
3
|
To run this example, make sure to set the following environment variables:
|
|
4
4
|
SENTRY_DSN
|
|
@@ -63,7 +63,7 @@ def create_app() -> FastAPI:
|
|
|
63
63
|
FastAPI: The configured FastAPI application.
|
|
64
64
|
"""
|
|
65
65
|
app = FastAPI(
|
|
66
|
-
title="
|
|
66
|
+
title="GL Connectors SDK - Sentry with Open Telemetry",
|
|
67
67
|
description="This is a simple FastAPI app to test Sentry with Open Telemetry.",
|
|
68
68
|
version="0.0.1",
|
|
69
69
|
docs_url=None,
|
|
@@ -39,6 +39,15 @@ async def main():
|
|
|
39
39
|
print(chunk["content"], end="", flush=True)
|
|
40
40
|
if chunk.get("metadata"):
|
|
41
41
|
print(f"\nMetadata: {chunk['metadata']}", end="\n\n", flush=True)
|
|
42
|
+
tool_info = chunk.get("metadata", {}).get("tool_info") if isinstance(chunk.get("metadata"), dict) else None
|
|
43
|
+
if isinstance(tool_info, dict):
|
|
44
|
+
for tool_call in tool_info.get("tool_calls", []):
|
|
45
|
+
if tool_call.get("name") == "data_visualizer":
|
|
46
|
+
data_source = tool_call.get("args", {}).get("data_source")
|
|
47
|
+
if not (isinstance(data_source, str) and data_source.startswith("$tool_output.")):
|
|
48
|
+
raise RuntimeError(
|
|
49
|
+
"Tool output sharing failed: expected data_source to reference $tool_output.<call_id>."
|
|
50
|
+
)
|
|
42
51
|
print("\n")
|
|
43
52
|
|
|
44
53
|
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Tool to multiply two integers.
|
|
2
|
+
|
|
3
|
+
Author: Putu Ravindra Wiguna (putu.r.wiguna@gdplabs.id)
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from langchain_core.tools import BaseTool
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class MultiplyToolInput(BaseModel):
|
|
11
|
+
"""Input schema for the MultiplyTool."""
|
|
12
|
+
|
|
13
|
+
a: int = Field(..., description="First factor.")
|
|
14
|
+
b: int = Field(..., description="Second factor.")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class MultiplyToolConfig(BaseModel):
|
|
18
|
+
"""Configuration for MultiplyTool."""
|
|
19
|
+
|
|
20
|
+
offset: int = Field(default=0, description="Offset to add to the result.")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class MultiplyTool(BaseTool):
|
|
24
|
+
"""Tool to multiply two integers."""
|
|
25
|
+
|
|
26
|
+
name: str = "multiply"
|
|
27
|
+
description: str = "Multiply two integers."
|
|
28
|
+
args_schema: type[BaseModel] = MultiplyToolInput
|
|
29
|
+
tool_config_schema: type[BaseModel] = MultiplyToolConfig
|
|
30
|
+
|
|
31
|
+
def _run(self, a: int, b: int) -> int:
|
|
32
|
+
"""Return the product of two integers."""
|
|
33
|
+
offset = 0
|
|
34
|
+
if hasattr(self, "get_tool_config"):
|
|
35
|
+
config = self.get_tool_config()
|
|
36
|
+
if config:
|
|
37
|
+
offset = getattr(config, "offset", 0)
|
|
38
|
+
|
|
39
|
+
return a * b + offset
|
|
40
|
+
|
|
41
|
+
async def _arun(self, a: int, b: int) -> int:
|
|
42
|
+
"""Return the product of two integers asynchronously."""
|
|
43
|
+
return self._run(a=a, b=b)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from langchain_core.tools import BaseTool
|
|
2
|
+
from pydantic import BaseModel
|
|
3
|
+
|
|
4
|
+
class MultiplyToolInput(BaseModel):
|
|
5
|
+
"""Input schema for the MultiplyTool."""
|
|
6
|
+
a: int
|
|
7
|
+
b: int
|
|
8
|
+
|
|
9
|
+
class MultiplyToolConfig(BaseModel):
|
|
10
|
+
"""Configuration for MultiplyTool."""
|
|
11
|
+
offset: int
|
|
12
|
+
|
|
13
|
+
class MultiplyTool(BaseTool):
|
|
14
|
+
"""Tool to multiply two integers."""
|
|
15
|
+
name: str
|
|
16
|
+
description: str
|
|
17
|
+
args_schema: type[BaseModel]
|
|
18
|
+
tool_config_schema: type[BaseModel]
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# flake8: noqa: F401
|
|
2
|
+
"""Guardrails package for content filtering and safety checks.
|
|
3
|
+
|
|
4
|
+
This package provides modular guardrail engines and managers for filtering
|
|
5
|
+
harmful content in AI agent interactions. All components support lazy loading
|
|
6
|
+
to work with optional dependencies.
|
|
7
|
+
|
|
8
|
+
Example:
|
|
9
|
+
Basic usage with a phrase matcher engine:
|
|
10
|
+
|
|
11
|
+
.. code-block:: python
|
|
12
|
+
|
|
13
|
+
from aip_agents.guardrails import GuardrailManager, GuardrailMiddleware
|
|
14
|
+
from aip_agents.guardrails.engines import PhraseMatcherEngine
|
|
15
|
+
from aip_agents.guardrails.schemas import GuardrailMode
|
|
16
|
+
|
|
17
|
+
# Create a guardrail engine
|
|
18
|
+
engine = PhraseMatcherEngine(
|
|
19
|
+
banned_phrases=["spam", "inappropriate"]
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
# Create a manager
|
|
23
|
+
manager = GuardrailManager(engines=[engine])
|
|
24
|
+
|
|
25
|
+
# Create middleware for agent integration
|
|
26
|
+
middleware = GuardrailMiddleware(guardrail_manager=manager)
|
|
27
|
+
|
|
28
|
+
# Use with agent (components are lazy-loaded)
|
|
29
|
+
from aip_agents.agent import LangGraphReactAgent
|
|
30
|
+
agent = LangGraphReactAgent(
|
|
31
|
+
name="my_agent",
|
|
32
|
+
guardrail=manager,
|
|
33
|
+
# ... other agent config
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
Authors:
|
|
37
|
+
Reinhart Linanda (reinhart.linanda@gdplabs.id)
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
from typing import TYPE_CHECKING, Any
|
|
41
|
+
|
|
42
|
+
if TYPE_CHECKING:
|
|
43
|
+
from aip_agents.guardrails.exceptions import GuardrailViolationError
|
|
44
|
+
from aip_agents.guardrails.manager import GuardrailManager
|
|
45
|
+
from aip_agents.guardrails.middleware import GuardrailMiddleware
|
|
46
|
+
from aip_agents.guardrails.schemas import (
|
|
47
|
+
BaseGuardrailEngineConfig,
|
|
48
|
+
GuardrailInput,
|
|
49
|
+
GuardrailMode,
|
|
50
|
+
GuardrailResult,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
_IMPORT_MAP = {
|
|
55
|
+
"GuardrailViolationError": "aip_agents.guardrails.exceptions",
|
|
56
|
+
"GuardrailManager": "aip_agents.guardrails.manager",
|
|
57
|
+
"GuardrailMiddleware": "aip_agents.guardrails.middleware",
|
|
58
|
+
"BaseGuardrailEngineConfig": "aip_agents.guardrails.schemas",
|
|
59
|
+
"GuardrailMode": "aip_agents.guardrails.schemas",
|
|
60
|
+
"GuardrailInput": "aip_agents.guardrails.schemas",
|
|
61
|
+
"GuardrailResult": "aip_agents.guardrails.schemas",
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
_cache: dict[str, Any] = {}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def __getattr__(name: str) -> Any:
|
|
68
|
+
"""Lazy import components on first access."""
|
|
69
|
+
if name in _cache:
|
|
70
|
+
return _cache[name]
|
|
71
|
+
|
|
72
|
+
if name in _IMPORT_MAP:
|
|
73
|
+
try:
|
|
74
|
+
module = __import__(_IMPORT_MAP[name], fromlist=[name])
|
|
75
|
+
_cache[name] = getattr(module, name)
|
|
76
|
+
return _cache[name]
|
|
77
|
+
except ImportError as e:
|
|
78
|
+
raise ImportError(f"Failed to import {name}. Optional dependencies may be missing: {e}") from e
|
|
79
|
+
|
|
80
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
__all__ = list(_IMPORT_MAP.keys())
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
from aip_agents.guardrails.exceptions import GuardrailViolationError as GuardrailViolationError
|
|
2
|
+
from aip_agents.guardrails.manager import GuardrailManager as GuardrailManager
|
|
3
|
+
from aip_agents.guardrails.middleware import GuardrailMiddleware as GuardrailMiddleware
|
|
4
|
+
from aip_agents.guardrails.schemas import BaseGuardrailEngineConfig as BaseGuardrailEngineConfig, GuardrailInput as GuardrailInput, GuardrailMode as GuardrailMode, GuardrailResult as GuardrailResult
|
|
5
|
+
|
|
6
|
+
__all__ = ['GuardrailViolationError', 'GuardrailManager', 'GuardrailMiddleware', 'BaseGuardrailEngineConfig', 'GuardrailMode', 'GuardrailInput', 'GuardrailResult']
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# flake8: noqa: F401
|
|
2
|
+
"""Guardrail engines package with lazy loading support.
|
|
3
|
+
|
|
4
|
+
This package provides guardrail engines that wrap GL SDK implementations.
|
|
5
|
+
Engines are loaded lazily to support optional dependencies.
|
|
6
|
+
|
|
7
|
+
Example:
|
|
8
|
+
Import and use guardrail engines:
|
|
9
|
+
|
|
10
|
+
.. code-block:: python
|
|
11
|
+
|
|
12
|
+
# Lazy import - works even if gllm-guardrail is not installed
|
|
13
|
+
from aip_agents.guardrails.engines import PhraseMatcherEngine, NemoGuardrailEngine
|
|
14
|
+
|
|
15
|
+
# Create a phrase matcher engine
|
|
16
|
+
phrase_engine = PhraseMatcherEngine(
|
|
17
|
+
banned_phrases=["spam", "inappropriate"]
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
# Create a NeMo guardrail engine (requires gllm-guardrail)
|
|
21
|
+
nemo_engine = NemoGuardrailEngine(
|
|
22
|
+
# NeMo-specific configuration
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
# Use with GuardrailManager
|
|
26
|
+
from aip_agents.guardrails import GuardrailManager
|
|
27
|
+
manager = GuardrailManager(engines=[phrase_engine, nemo_engine])
|
|
28
|
+
|
|
29
|
+
Note:
|
|
30
|
+
All engines support lazy loading. If `gllm-guardrail` is not installed,
|
|
31
|
+
importing these engines will raise an ImportError only when actually
|
|
32
|
+
instantiated, not at import time.
|
|
33
|
+
|
|
34
|
+
Authors:
|
|
35
|
+
Reinhart Linanda (reinhart.linanda@gdplabs.id)
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
from typing import TYPE_CHECKING, Any
|
|
39
|
+
|
|
40
|
+
if TYPE_CHECKING:
|
|
41
|
+
from aip_agents.guardrails.engines.nemo import NemoGuardrailEngine
|
|
42
|
+
from aip_agents.guardrails.engines.phrase_matcher import PhraseMatcherEngine
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
_IMPORT_MAP = {
|
|
46
|
+
"NemoGuardrailEngine": "aip_agents.guardrails.engines.nemo",
|
|
47
|
+
"PhraseMatcherEngine": "aip_agents.guardrails.engines.phrase_matcher",
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
_cache: dict[str, Any] = {}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def __getattr__(name: str) -> Any:
|
|
54
|
+
"""Lazy import engines on first access."""
|
|
55
|
+
if name in _cache:
|
|
56
|
+
return _cache[name]
|
|
57
|
+
|
|
58
|
+
if name in _IMPORT_MAP:
|
|
59
|
+
try:
|
|
60
|
+
module = __import__(_IMPORT_MAP[name], fromlist=[name])
|
|
61
|
+
_cache[name] = getattr(module, name)
|
|
62
|
+
return _cache[name]
|
|
63
|
+
except ImportError as e:
|
|
64
|
+
raise ImportError(f"Failed to import {name}. Optional dependencies may be missing: {e}") from e
|
|
65
|
+
|
|
66
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
__all__ = list(_IMPORT_MAP.keys())
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""Base interfaces and protocols for guardrail engines.
|
|
2
|
+
|
|
3
|
+
This module defines the base protocol that all guardrail engines must implement,
|
|
4
|
+
providing a consistent interface for content safety checking.
|
|
5
|
+
|
|
6
|
+
Authors:
|
|
7
|
+
Reinhart Linanda (reinhart.linanda@gdplabs.id)
|
|
8
|
+
Christian Trisno Sen Long Chen (christian.t.s.l.chen@gdplabs.id)
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from abc import ABC, abstractmethod
|
|
12
|
+
from typing import Protocol
|
|
13
|
+
|
|
14
|
+
from aip_agents.guardrails.schemas import (
|
|
15
|
+
BaseGuardrailEngineConfig,
|
|
16
|
+
GuardrailResult,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class GuardrailEngine(Protocol):
|
|
21
|
+
"""Protocol defining the interface for guardrail engines.
|
|
22
|
+
|
|
23
|
+
All guardrail engines must implement this protocol to be compatible
|
|
24
|
+
with GuardrailManager. Engines check content for safety violations.
|
|
25
|
+
|
|
26
|
+
Attributes:
|
|
27
|
+
config: Configuration for this engine's behavior
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
config: BaseGuardrailEngineConfig
|
|
31
|
+
|
|
32
|
+
@abstractmethod
|
|
33
|
+
async def check_input(self, content: str) -> GuardrailResult:
|
|
34
|
+
"""Check user input content for safety violations.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
content: The user input content to check
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
GuardrailResult indicating if content is safe
|
|
41
|
+
"""
|
|
42
|
+
... # pragma: no cover
|
|
43
|
+
|
|
44
|
+
@abstractmethod
|
|
45
|
+
async def check_output(self, content: str) -> GuardrailResult:
|
|
46
|
+
"""Check AI output content for safety violations.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
content: The AI output content to check
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
GuardrailResult indicating if content is safe
|
|
53
|
+
"""
|
|
54
|
+
... # pragma: no cover
|
|
55
|
+
|
|
56
|
+
@abstractmethod
|
|
57
|
+
def model_dump(self) -> dict:
|
|
58
|
+
"""Serialize engine configuration into a JSON-compatible dictionary."""
|
|
59
|
+
... # pragma: no cover
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class BaseGuardrailEngine(ABC):
|
|
63
|
+
"""Abstract base class for guardrail engines.
|
|
64
|
+
|
|
65
|
+
Provides common functionality and ensures proper configuration handling.
|
|
66
|
+
Concrete engines should inherit from this class.
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
def __init__(self, config: BaseGuardrailEngineConfig | None = None) -> None:
|
|
70
|
+
"""Initialize the engine with configuration.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
config: Engine configuration. Uses defaults if None provided.
|
|
74
|
+
"""
|
|
75
|
+
self.config = config or BaseGuardrailEngineConfig()
|
|
76
|
+
|
|
77
|
+
@abstractmethod
|
|
78
|
+
async def check_input(self, content: str) -> GuardrailResult:
|
|
79
|
+
"""Check user input content for safety violations."""
|
|
80
|
+
... # pragma: no cover
|
|
81
|
+
|
|
82
|
+
@abstractmethod
|
|
83
|
+
async def check_output(self, content: str) -> GuardrailResult:
|
|
84
|
+
"""Check AI output content for safety violations."""
|
|
85
|
+
... # pragma: no cover
|
|
86
|
+
|
|
87
|
+
@abstractmethod
|
|
88
|
+
def model_dump(self) -> dict:
|
|
89
|
+
"""Serialize engine configuration into a JSON-compatible dictionary."""
|
|
90
|
+
... # pragma: no cover
|