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.
Files changed (149) hide show
  1. aip_agents/agent/__init__.py +44 -4
  2. aip_agents/agent/base_langgraph_agent.py +169 -74
  3. aip_agents/agent/base_langgraph_agent.pyi +3 -2
  4. aip_agents/agent/langgraph_memory_enhancer_agent.py +368 -34
  5. aip_agents/agent/langgraph_memory_enhancer_agent.pyi +3 -2
  6. aip_agents/agent/langgraph_react_agent.py +424 -35
  7. aip_agents/agent/langgraph_react_agent.pyi +46 -2
  8. aip_agents/examples/{hello_world_langgraph_bosa_twitter.py → hello_world_langgraph_gl_connector_twitter.py} +10 -7
  9. aip_agents/examples/hello_world_langgraph_gl_connector_twitter.pyi +5 -0
  10. aip_agents/examples/hello_world_ptc.py +49 -0
  11. aip_agents/examples/hello_world_ptc.pyi +5 -0
  12. aip_agents/examples/hello_world_ptc_custom_tools.py +83 -0
  13. aip_agents/examples/hello_world_ptc_custom_tools.pyi +7 -0
  14. aip_agents/examples/hello_world_sentry.py +2 -2
  15. aip_agents/examples/hello_world_tool_output_client.py +9 -0
  16. aip_agents/examples/tools/multiply_tool.py +43 -0
  17. aip_agents/examples/tools/multiply_tool.pyi +18 -0
  18. aip_agents/guardrails/__init__.py +83 -0
  19. aip_agents/guardrails/__init__.pyi +6 -0
  20. aip_agents/guardrails/engines/__init__.py +69 -0
  21. aip_agents/guardrails/engines/__init__.pyi +4 -0
  22. aip_agents/guardrails/engines/base.py +90 -0
  23. aip_agents/guardrails/engines/base.pyi +61 -0
  24. aip_agents/guardrails/engines/nemo.py +101 -0
  25. aip_agents/guardrails/engines/nemo.pyi +46 -0
  26. aip_agents/guardrails/engines/phrase_matcher.py +113 -0
  27. aip_agents/guardrails/engines/phrase_matcher.pyi +48 -0
  28. aip_agents/guardrails/exceptions.py +39 -0
  29. aip_agents/guardrails/exceptions.pyi +23 -0
  30. aip_agents/guardrails/manager.py +163 -0
  31. aip_agents/guardrails/manager.pyi +42 -0
  32. aip_agents/guardrails/middleware.py +199 -0
  33. aip_agents/guardrails/middleware.pyi +87 -0
  34. aip_agents/guardrails/schemas.py +63 -0
  35. aip_agents/guardrails/schemas.pyi +43 -0
  36. aip_agents/guardrails/utils.py +45 -0
  37. aip_agents/guardrails/utils.pyi +19 -0
  38. aip_agents/mcp/client/__init__.py +38 -2
  39. aip_agents/mcp/client/connection_manager.py +36 -1
  40. aip_agents/mcp/client/connection_manager.pyi +3 -0
  41. aip_agents/mcp/client/persistent_session.py +318 -65
  42. aip_agents/mcp/client/persistent_session.pyi +9 -0
  43. aip_agents/mcp/client/transports.py +52 -4
  44. aip_agents/mcp/client/transports.pyi +9 -0
  45. aip_agents/memory/adapters/base_adapter.py +98 -0
  46. aip_agents/memory/adapters/base_adapter.pyi +25 -0
  47. aip_agents/middleware/base.py +8 -0
  48. aip_agents/middleware/base.pyi +4 -0
  49. aip_agents/middleware/manager.py +22 -0
  50. aip_agents/middleware/manager.pyi +4 -0
  51. aip_agents/ptc/__init__.py +87 -0
  52. aip_agents/ptc/__init__.pyi +14 -0
  53. aip_agents/ptc/custom_tools.py +473 -0
  54. aip_agents/ptc/custom_tools.pyi +184 -0
  55. aip_agents/ptc/custom_tools_payload.py +400 -0
  56. aip_agents/ptc/custom_tools_payload.pyi +31 -0
  57. aip_agents/ptc/custom_tools_templates/__init__.py +1 -0
  58. aip_agents/ptc/custom_tools_templates/__init__.pyi +0 -0
  59. aip_agents/ptc/custom_tools_templates/custom_build_function.py.template +23 -0
  60. aip_agents/ptc/custom_tools_templates/custom_init.py.template +15 -0
  61. aip_agents/ptc/custom_tools_templates/custom_invoke.py.template +60 -0
  62. aip_agents/ptc/custom_tools_templates/custom_registry.py.template +87 -0
  63. aip_agents/ptc/custom_tools_templates/custom_sources_init.py.template +7 -0
  64. aip_agents/ptc/custom_tools_templates/custom_wrapper.py.template +19 -0
  65. aip_agents/ptc/doc_gen.py +122 -0
  66. aip_agents/ptc/doc_gen.pyi +40 -0
  67. aip_agents/ptc/exceptions.py +57 -0
  68. aip_agents/ptc/exceptions.pyi +37 -0
  69. aip_agents/ptc/executor.py +261 -0
  70. aip_agents/ptc/executor.pyi +99 -0
  71. aip_agents/ptc/mcp/__init__.py +45 -0
  72. aip_agents/ptc/mcp/__init__.pyi +7 -0
  73. aip_agents/ptc/mcp/sandbox_bridge.py +668 -0
  74. aip_agents/ptc/mcp/sandbox_bridge.pyi +47 -0
  75. aip_agents/ptc/mcp/templates/__init__.py +1 -0
  76. aip_agents/ptc/mcp/templates/__init__.pyi +0 -0
  77. aip_agents/ptc/mcp/templates/mcp_client.py.template +239 -0
  78. aip_agents/ptc/naming.py +196 -0
  79. aip_agents/ptc/naming.pyi +85 -0
  80. aip_agents/ptc/payload.py +26 -0
  81. aip_agents/ptc/payload.pyi +15 -0
  82. aip_agents/ptc/prompt_builder.py +673 -0
  83. aip_agents/ptc/prompt_builder.pyi +59 -0
  84. aip_agents/ptc/ptc_helper.py +16 -0
  85. aip_agents/ptc/ptc_helper.pyi +1 -0
  86. aip_agents/ptc/sandbox_bridge.py +256 -0
  87. aip_agents/ptc/sandbox_bridge.pyi +38 -0
  88. aip_agents/ptc/template_utils.py +33 -0
  89. aip_agents/ptc/template_utils.pyi +13 -0
  90. aip_agents/ptc/templates/__init__.py +1 -0
  91. aip_agents/ptc/templates/__init__.pyi +0 -0
  92. aip_agents/ptc/templates/ptc_helper.py.template +134 -0
  93. aip_agents/ptc/tool_def_helpers.py +101 -0
  94. aip_agents/ptc/tool_def_helpers.pyi +38 -0
  95. aip_agents/ptc/tool_enrichment.py +163 -0
  96. aip_agents/ptc/tool_enrichment.pyi +60 -0
  97. aip_agents/sandbox/__init__.py +43 -0
  98. aip_agents/sandbox/__init__.pyi +5 -0
  99. aip_agents/sandbox/defaults.py +205 -0
  100. aip_agents/sandbox/defaults.pyi +30 -0
  101. aip_agents/sandbox/e2b_runtime.py +295 -0
  102. aip_agents/sandbox/e2b_runtime.pyi +57 -0
  103. aip_agents/sandbox/template_builder.py +131 -0
  104. aip_agents/sandbox/template_builder.pyi +36 -0
  105. aip_agents/sandbox/types.py +24 -0
  106. aip_agents/sandbox/types.pyi +14 -0
  107. aip_agents/sandbox/validation.py +50 -0
  108. aip_agents/sandbox/validation.pyi +20 -0
  109. aip_agents/sentry/__init__.py +1 -1
  110. aip_agents/sentry/sentry.py +33 -12
  111. aip_agents/sentry/sentry.pyi +5 -4
  112. aip_agents/tools/__init__.py +20 -3
  113. aip_agents/tools/__init__.pyi +4 -2
  114. aip_agents/tools/browser_use/browser_use_tool.py +8 -0
  115. aip_agents/tools/browser_use/streaming.py +2 -0
  116. aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.py +80 -31
  117. aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.pyi +25 -9
  118. aip_agents/tools/code_sandbox/e2b_sandbox_tool.py +6 -6
  119. aip_agents/tools/constants.py +24 -12
  120. aip_agents/tools/constants.pyi +14 -11
  121. aip_agents/tools/date_range_tool.py +554 -0
  122. aip_agents/tools/date_range_tool.pyi +21 -0
  123. aip_agents/tools/execute_ptc_code.py +357 -0
  124. aip_agents/tools/execute_ptc_code.pyi +90 -0
  125. aip_agents/tools/gl_connector/__init__.py +1 -1
  126. aip_agents/tools/gl_connector/tool.py +62 -30
  127. aip_agents/tools/gl_connector/tool.pyi +3 -3
  128. aip_agents/tools/gl_connector_tools.py +119 -0
  129. aip_agents/tools/gl_connector_tools.pyi +39 -0
  130. aip_agents/tools/memory_search/__init__.py +8 -1
  131. aip_agents/tools/memory_search/__init__.pyi +3 -3
  132. aip_agents/tools/memory_search/mem0.py +114 -1
  133. aip_agents/tools/memory_search/mem0.pyi +11 -1
  134. aip_agents/tools/memory_search/schema.py +33 -0
  135. aip_agents/tools/memory_search/schema.pyi +10 -0
  136. aip_agents/tools/memory_search_tool.py +8 -0
  137. aip_agents/tools/memory_search_tool.pyi +2 -2
  138. aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.py +26 -1
  139. aip_agents/utils/langgraph/tool_output_management.py +80 -0
  140. aip_agents/utils/langgraph/tool_output_management.pyi +37 -0
  141. {aip_agents_binary-0.5.21.dist-info → aip_agents_binary-0.6.8.dist-info}/METADATA +14 -22
  142. {aip_agents_binary-0.5.21.dist-info → aip_agents_binary-0.6.8.dist-info}/RECORD +144 -58
  143. {aip_agents_binary-0.5.21.dist-info → aip_agents_binary-0.6.8.dist-info}/WHEEL +1 -1
  144. aip_agents/examples/demo_memory_recall.py +0 -401
  145. aip_agents/examples/demo_memory_recall.pyi +0 -58
  146. aip_agents/examples/hello_world_langgraph_bosa_twitter.pyi +0 -5
  147. aip_agents/tools/bosa_tools.py +0 -105
  148. aip_agents/tools/bosa_tools.pyi +0 -37
  149. {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 bosa support example demonstrating asynchronous run.
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 BOSA_AUTOMATED_TOOLS
13
+ from aip_agents.tools import GL_CONNECTORS_AUTOMATED_TOOLS
13
14
 
15
+ load_dotenv(override=True)
14
16
 
15
- async def langgraph_bosa_example():
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 = "BOSAConnectorTwitterAgent"
21
+ agent_name = "GLConnectorTwitterAgent"
19
22
 
20
23
  langgraph_agent = LangGraphAgent(
21
24
  name=agent_name,
22
- instruction="You are a helpful assistant that use BOSA connector to connect with Twitter API.",
25
+ instruction="You are a helpful assistant that uses GL Connectors to connect with the Twitter API.",
23
26
  model=model,
24
- tools=BOSA_AUTOMATED_TOOLS["twitter"],
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(langgraph_bosa_example())
44
+ asyncio.run(langgraph_gl_connector_example())
@@ -0,0 +1,5 @@
1
+ from aip_agents.agent import LangGraphAgent as LangGraphAgent
2
+ from aip_agents.tools import GL_CONNECTORS_AUTOMATED_TOOLS as GL_CONNECTORS_AUTOMATED_TOOLS
3
+
4
+ async def langgraph_gl_connector_example() -> None:
5
+ """Demonstrates the LangGraphAgent's arun method."""
@@ -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,5 @@
1
+ from aip_agents.agent import LangGraphReactAgent as LangGraphReactAgent
2
+ from aip_agents.ptc import PTCSandboxConfig as PTCSandboxConfig, PromptConfig as PromptConfig
3
+
4
+ async def main() -> None:
5
+ """Run a hello-world PTC flow."""
@@ -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 BOSA SDK.
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="Bosa SDK - Sentry with Open Telemetry",
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,4 @@
1
+ from aip_agents.guardrails.engines.nemo import NemoGuardrailEngine as NemoGuardrailEngine
2
+ from aip_agents.guardrails.engines.phrase_matcher import PhraseMatcherEngine as PhraseMatcherEngine
3
+
4
+ __all__ = ['NemoGuardrailEngine', 'PhraseMatcherEngine']
@@ -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