aip-agents-binary 0.5.25b8__py3-none-any.whl → 0.6.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aip_agents/__init__.pyi +19 -0
- aip_agents/a2a/__init__.pyi +3 -0
- aip_agents/a2a/server/__init__.pyi +4 -0
- aip_agents/a2a/server/base_executor.pyi +73 -0
- aip_agents/a2a/server/google_adk_executor.pyi +51 -0
- aip_agents/a2a/server/langflow_executor.pyi +43 -0
- aip_agents/a2a/server/langgraph_executor.pyi +47 -0
- aip_agents/a2a/types.pyi +132 -0
- aip_agents/agent/__init__.pyi +9 -0
- aip_agents/agent/base_agent.pyi +221 -0
- aip_agents/agent/base_langgraph_agent.py +137 -68
- aip_agents/agent/base_langgraph_agent.pyi +233 -0
- aip_agents/agent/google_adk_agent.pyi +141 -0
- aip_agents/agent/google_adk_constants.pyi +3 -0
- aip_agents/agent/hitl/__init__.pyi +6 -0
- aip_agents/agent/hitl/config.pyi +15 -0
- aip_agents/agent/hitl/langgraph_hitl_mixin.pyi +42 -0
- aip_agents/agent/hitl/manager.pyi +200 -0
- aip_agents/agent/hitl/models.pyi +3 -0
- aip_agents/agent/hitl/prompt/__init__.pyi +4 -0
- aip_agents/agent/hitl/prompt/base.pyi +24 -0
- aip_agents/agent/hitl/prompt/deferred.pyi +30 -0
- aip_agents/agent/hitl/registry.pyi +101 -0
- aip_agents/agent/interface.pyi +81 -0
- aip_agents/agent/interfaces.pyi +44 -0
- aip_agents/agent/langflow_agent.pyi +133 -0
- aip_agents/agent/langgraph_memory_enhancer_agent.pyi +49 -0
- aip_agents/agent/langgraph_react_agent.py +58 -14
- aip_agents/agent/langgraph_react_agent.pyi +131 -0
- aip_agents/agent/system_instruction_context.pyi +13 -0
- aip_agents/clients/__init__.pyi +4 -0
- aip_agents/clients/langflow/__init__.pyi +4 -0
- aip_agents/clients/langflow/client.pyi +140 -0
- aip_agents/clients/langflow/types.pyi +7 -0
- aip_agents/constants.pyi +7 -0
- aip_agents/examples/__init__.pyi +0 -0
- aip_agents/examples/compare_streaming_client.py +2 -2
- aip_agents/examples/compare_streaming_client.pyi +48 -0
- aip_agents/examples/compare_streaming_server.py +1 -1
- aip_agents/examples/compare_streaming_server.pyi +18 -0
- aip_agents/examples/demo_memory_recall.pyi +58 -0
- aip_agents/examples/hello_world_a2a_google_adk_client.pyi +9 -0
- aip_agents/examples/hello_world_a2a_google_adk_client_agent.pyi +9 -0
- aip_agents/examples/hello_world_a2a_google_adk_client_streaming.pyi +9 -0
- aip_agents/examples/hello_world_a2a_google_adk_server.pyi +15 -0
- aip_agents/examples/hello_world_a2a_langchain_client.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langchain_client_agent.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langchain_client_streaming.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langchain_reference_server.pyi +15 -0
- aip_agents/examples/hello_world_a2a_langchain_server.pyi +15 -0
- aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.pyi +15 -0
- aip_agents/examples/hello_world_a2a_langflow_client.pyi +9 -0
- aip_agents/examples/hello_world_a2a_langflow_server.pyi +14 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_client.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_server.pyi +16 -0
- aip_agents/examples/hello_world_a2a_langgraph_client.pyi +9 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_agent.pyi +9 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_agent_lm_invoker.pyi +2 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming.pyi +9 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming_lm_invoker.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming_tool_streaming.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langgraph_server.pyi +14 -0
- aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.pyi +15 -0
- aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.pyi +15 -0
- aip_agents/examples/hello_world_a2a_mcp_langgraph.pyi +48 -0
- aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_client.pyi +48 -0
- aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_server.pyi +45 -0
- aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.pyi +5 -0
- aip_agents/examples/hello_world_a2a_with_metadata_langchain_server_lm_invoker.pyi +15 -0
- aip_agents/examples/hello_world_google_adk.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_mcp_http.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_mcp_http_stream.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_mcp_sse.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_mcp_sse_stream.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_mcp_stdio.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_mcp_stdio_stream.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_stream.pyi +5 -0
- aip_agents/examples/hello_world_langchain.pyi +5 -0
- aip_agents/examples/hello_world_langchain_lm_invoker.pyi +2 -0
- aip_agents/examples/hello_world_langchain_mcp_http.pyi +5 -0
- aip_agents/examples/hello_world_langchain_mcp_http_interactive.pyi +16 -0
- aip_agents/examples/hello_world_langchain_mcp_http_stream.pyi +5 -0
- aip_agents/examples/hello_world_langchain_mcp_multi_server.pyi +18 -0
- aip_agents/examples/hello_world_langchain_mcp_sse.pyi +5 -0
- aip_agents/examples/hello_world_langchain_mcp_sse_stream.pyi +5 -0
- aip_agents/examples/hello_world_langchain_mcp_stdio.pyi +5 -0
- aip_agents/examples/hello_world_langchain_mcp_stdio_stream.pyi +5 -0
- aip_agents/examples/hello_world_langchain_stream.pyi +5 -0
- aip_agents/examples/hello_world_langchain_stream_lm_invoker.pyi +5 -0
- aip_agents/examples/hello_world_langflow_agent.pyi +35 -0
- aip_agents/examples/hello_world_langgraph.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_gl_connector_twitter.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_mcp_http.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_mcp_http_stream.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_mcp_sse.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_mcp_sse_stream.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_mcp_stdio.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_mcp_stdio_stream.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_stream.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_stream_lm_invoker.pyi +5 -0
- aip_agents/examples/hello_world_model_switch_cli.pyi +30 -0
- aip_agents/examples/hello_world_multi_agent_adk.pyi +6 -0
- aip_agents/examples/hello_world_multi_agent_langchain.pyi +5 -0
- aip_agents/examples/hello_world_multi_agent_langgraph.pyi +5 -0
- aip_agents/examples/hello_world_multi_agent_langgraph_lm_invoker.pyi +5 -0
- aip_agents/examples/hello_world_pii_logger.pyi +5 -0
- aip_agents/examples/hello_world_sentry.pyi +21 -0
- aip_agents/examples/hello_world_step_limits.pyi +17 -0
- aip_agents/examples/hello_world_stock_a2a_server.pyi +17 -0
- aip_agents/examples/hello_world_tool_output_client.py +9 -0
- aip_agents/examples/hello_world_tool_output_client.pyi +5 -0
- aip_agents/examples/hello_world_tool_output_server.pyi +19 -0
- aip_agents/examples/hitl_demo.pyi +67 -0
- aip_agents/examples/pii_demo_langgraph_client.pyi +5 -0
- aip_agents/examples/pii_demo_langgraph_server.pyi +20 -0
- aip_agents/examples/pii_demo_multi_agent_client.pyi +5 -0
- aip_agents/examples/pii_demo_multi_agent_server.pyi +40 -0
- aip_agents/examples/todolist_planning_a2a_langchain_client.py +2 -2
- aip_agents/examples/todolist_planning_a2a_langchain_client.pyi +5 -0
- aip_agents/examples/todolist_planning_a2a_langgraph_server.py +1 -1
- aip_agents/examples/todolist_planning_a2a_langgraph_server.pyi +19 -0
- aip_agents/examples/tools/__init__.pyi +9 -0
- aip_agents/examples/tools/adk_arithmetic_tools.pyi +24 -0
- aip_agents/examples/tools/adk_weather_tool.pyi +18 -0
- aip_agents/examples/tools/data_generator_tool.pyi +15 -0
- aip_agents/examples/tools/data_visualization_tool.pyi +19 -0
- aip_agents/examples/tools/image_artifact_tool.pyi +26 -0
- aip_agents/examples/tools/langchain_arithmetic_tools.pyi +17 -0
- aip_agents/examples/tools/langchain_currency_exchange_tool.pyi +20 -0
- aip_agents/examples/tools/langchain_graph_artifact_tool.pyi +25 -0
- aip_agents/examples/tools/langchain_weather_tool.pyi +19 -0
- aip_agents/examples/tools/langgraph_streaming_tool.pyi +43 -0
- aip_agents/examples/tools/mock_retrieval_tool.pyi +13 -0
- aip_agents/examples/tools/pii_demo_tools.pyi +54 -0
- aip_agents/examples/tools/random_chart_tool.pyi +20 -0
- aip_agents/examples/tools/serper_tool.pyi +16 -0
- aip_agents/examples/tools/stock_tools.pyi +36 -0
- aip_agents/examples/tools/table_generator_tool.pyi +22 -0
- aip_agents/examples/tools/time_tool.pyi +15 -0
- aip_agents/examples/tools/weather_forecast_tool.pyi +14 -0
- aip_agents/guardrails/__init__.pyi +6 -0
- aip_agents/guardrails/engines/__init__.pyi +4 -0
- aip_agents/guardrails/engines/base.py +6 -6
- aip_agents/guardrails/engines/base.pyi +61 -0
- aip_agents/guardrails/engines/nemo.pyi +46 -0
- aip_agents/guardrails/engines/phrase_matcher.pyi +48 -0
- aip_agents/guardrails/exceptions.pyi +23 -0
- aip_agents/guardrails/manager.pyi +42 -0
- aip_agents/guardrails/middleware.pyi +87 -0
- aip_agents/guardrails/schemas.pyi +43 -0
- aip_agents/guardrails/utils.pyi +19 -0
- aip_agents/mcp/__init__.pyi +0 -0
- aip_agents/mcp/client/__init__.pyi +5 -0
- aip_agents/mcp/client/base_mcp_client.pyi +148 -0
- aip_agents/mcp/client/connection_manager.py +36 -1
- aip_agents/mcp/client/connection_manager.pyi +51 -0
- aip_agents/mcp/client/google_adk/__init__.pyi +3 -0
- aip_agents/mcp/client/google_adk/client.pyi +75 -0
- aip_agents/mcp/client/langchain/__init__.pyi +3 -0
- aip_agents/mcp/client/langchain/client.pyi +48 -0
- aip_agents/mcp/client/persistent_session.py +318 -68
- aip_agents/mcp/client/persistent_session.pyi +122 -0
- aip_agents/mcp/client/session_pool.pyi +101 -0
- aip_agents/mcp/client/transports.py +33 -2
- aip_agents/mcp/client/transports.pyi +132 -0
- aip_agents/mcp/utils/__init__.pyi +0 -0
- aip_agents/mcp/utils/config_validator.pyi +82 -0
- aip_agents/memory/__init__.pyi +5 -0
- aip_agents/memory/adapters/__init__.pyi +4 -0
- aip_agents/memory/adapters/base_adapter.pyi +150 -0
- aip_agents/memory/adapters/mem0.pyi +22 -0
- aip_agents/memory/base.pyi +60 -0
- aip_agents/memory/constants.pyi +25 -0
- aip_agents/memory/factory.pyi +24 -0
- aip_agents/memory/guidance.pyi +3 -0
- aip_agents/memory/simple_memory.pyi +23 -0
- aip_agents/middleware/__init__.pyi +5 -0
- aip_agents/middleware/base.pyi +75 -0
- aip_agents/middleware/manager.pyi +84 -0
- aip_agents/middleware/todolist.pyi +125 -0
- aip_agents/schema/__init__.pyi +9 -0
- aip_agents/schema/a2a.pyi +40 -0
- aip_agents/schema/agent.pyi +65 -0
- aip_agents/schema/hitl.pyi +89 -0
- aip_agents/schema/langgraph.pyi +28 -0
- aip_agents/schema/model_id.pyi +54 -0
- aip_agents/schema/step_limit.pyi +63 -0
- aip_agents/schema/storage.pyi +21 -0
- aip_agents/sentry/__init__.pyi +3 -0
- aip_agents/sentry/sentry.pyi +48 -0
- aip_agents/storage/__init__.pyi +8 -0
- aip_agents/storage/base.pyi +58 -0
- aip_agents/storage/clients/__init__.pyi +3 -0
- aip_agents/storage/clients/minio_client.pyi +137 -0
- aip_agents/storage/config.pyi +29 -0
- aip_agents/storage/providers/__init__.pyi +5 -0
- aip_agents/storage/providers/base.pyi +88 -0
- aip_agents/storage/providers/memory.pyi +79 -0
- aip_agents/storage/providers/object_storage.pyi +98 -0
- aip_agents/tools/__init__.pyi +9 -0
- aip_agents/tools/browser_use/__init__.pyi +14 -0
- aip_agents/tools/browser_use/action_parser.pyi +18 -0
- aip_agents/tools/browser_use/browser_use_tool.py +8 -0
- aip_agents/tools/browser_use/browser_use_tool.pyi +50 -0
- aip_agents/tools/browser_use/llm_config.pyi +52 -0
- aip_agents/tools/browser_use/minio_storage.pyi +109 -0
- aip_agents/tools/browser_use/schemas.pyi +32 -0
- aip_agents/tools/browser_use/session.pyi +4 -0
- aip_agents/tools/browser_use/session_errors.pyi +53 -0
- aip_agents/tools/browser_use/steel_session_recording.pyi +63 -0
- aip_agents/tools/browser_use/streaming.py +2 -0
- aip_agents/tools/browser_use/streaming.pyi +81 -0
- aip_agents/tools/browser_use/structured_data_parser.pyi +86 -0
- aip_agents/tools/browser_use/structured_data_recovery.pyi +43 -0
- aip_agents/tools/browser_use/types.pyi +45 -0
- aip_agents/tools/code_sandbox/__init__.pyi +3 -0
- aip_agents/tools/code_sandbox/constant.pyi +4 -0
- aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.pyi +102 -0
- aip_agents/tools/code_sandbox/e2b_sandbox_tool.pyi +29 -0
- aip_agents/tools/constants.pyi +138 -0
- aip_agents/tools/document_loader/__init__.pyi +7 -0
- aip_agents/tools/document_loader/base_reader.pyi +75 -0
- aip_agents/tools/document_loader/docx_reader_tool.pyi +10 -0
- aip_agents/tools/document_loader/excel_reader_tool.pyi +26 -0
- aip_agents/tools/document_loader/pdf_reader_tool.pyi +11 -0
- aip_agents/tools/document_loader/pdf_splitter.pyi +18 -0
- aip_agents/tools/gl_connector/__init__.pyi +3 -0
- aip_agents/tools/gl_connector/tool.pyi +74 -0
- aip_agents/tools/gl_connector_tools.pyi +39 -0
- aip_agents/tools/memory_search/__init__.pyi +5 -0
- aip_agents/tools/memory_search/base.pyi +69 -0
- aip_agents/tools/memory_search/mem0.pyi +19 -0
- aip_agents/tools/memory_search/schema.pyi +15 -0
- aip_agents/tools/memory_search_tool.pyi +3 -0
- aip_agents/tools/time_tool.pyi +16 -0
- aip_agents/tools/tool_config_injector.pyi +26 -0
- aip_agents/tools/web_search/__init__.pyi +3 -0
- aip_agents/tools/web_search/serper_tool.pyi +19 -0
- aip_agents/types/__init__.pyi +36 -0
- aip_agents/types/a2a_events.pyi +3 -0
- aip_agents/utils/__init__.pyi +11 -0
- aip_agents/utils/a2a_connector.pyi +146 -0
- aip_agents/utils/artifact_helpers.pyi +203 -0
- aip_agents/utils/constants.pyi +10 -0
- aip_agents/utils/datetime/__init__.pyi +4 -0
- aip_agents/utils/datetime/normalization.pyi +95 -0
- aip_agents/utils/datetime/timezone.pyi +48 -0
- aip_agents/utils/env_loader.pyi +10 -0
- aip_agents/utils/event_handler_registry.pyi +23 -0
- aip_agents/utils/file_prompt_utils.pyi +21 -0
- aip_agents/utils/final_response_builder.pyi +34 -0
- aip_agents/utils/formatter_llm_client.pyi +71 -0
- aip_agents/utils/langgraph/__init__.pyi +3 -0
- aip_agents/utils/langgraph/converter.pyi +49 -0
- aip_agents/utils/langgraph/tool_managers/__init__.pyi +5 -0
- aip_agents/utils/langgraph/tool_managers/a2a_tool_manager.pyi +35 -0
- aip_agents/utils/langgraph/tool_managers/base_tool_manager.pyi +48 -0
- aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.py +26 -1
- aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.pyi +56 -0
- aip_agents/utils/langgraph/tool_output_management.py +80 -0
- aip_agents/utils/langgraph/tool_output_management.pyi +329 -0
- aip_agents/utils/logger.pyi +60 -0
- aip_agents/utils/metadata/__init__.pyi +5 -0
- aip_agents/utils/metadata/activity_metadata_helper.pyi +25 -0
- aip_agents/utils/metadata/activity_narrative/__init__.pyi +7 -0
- aip_agents/utils/metadata/activity_narrative/builder.pyi +35 -0
- aip_agents/utils/metadata/activity_narrative/constants.pyi +10 -0
- aip_agents/utils/metadata/activity_narrative/context.pyi +32 -0
- aip_agents/utils/metadata/activity_narrative/formatters.pyi +48 -0
- aip_agents/utils/metadata/activity_narrative/utils.pyi +12 -0
- aip_agents/utils/metadata/schemas/__init__.pyi +4 -0
- aip_agents/utils/metadata/schemas/activity_schema.pyi +18 -0
- aip_agents/utils/metadata/schemas/thinking_schema.pyi +20 -0
- aip_agents/utils/metadata/thinking_metadata_helper.pyi +4 -0
- aip_agents/utils/metadata_helper.pyi +117 -0
- aip_agents/utils/name_preprocessor/__init__.pyi +6 -0
- aip_agents/utils/name_preprocessor/base_name_preprocessor.pyi +52 -0
- aip_agents/utils/name_preprocessor/google_name_preprocessor.pyi +38 -0
- aip_agents/utils/name_preprocessor/name_preprocessor.pyi +41 -0
- aip_agents/utils/name_preprocessor/openai_name_preprocessor.pyi +34 -0
- aip_agents/utils/pii/__init__.pyi +5 -0
- aip_agents/utils/pii/pii_handler.pyi +96 -0
- aip_agents/utils/pii/pii_helper.pyi +78 -0
- aip_agents/utils/pii/uuid_deanonymizer_mapping.pyi +73 -0
- aip_agents/utils/reference_helper.pyi +81 -0
- aip_agents/utils/sse_chunk_transformer.pyi +166 -0
- aip_agents/utils/step_limit_manager.pyi +112 -0
- aip_agents/utils/token_usage_helper.pyi +60 -0
- {aip_agents_binary-0.5.25b8.dist-info → aip_agents_binary-0.6.0.dist-info}/METADATA +51 -48
- aip_agents_binary-0.6.0.dist-info/RECORD +566 -0
- aip_agents_binary-0.5.25b8.dist-info/RECORD +0 -290
- {aip_agents_binary-0.5.25b8.dist-info → aip_agents_binary-0.6.0.dist-info}/WHEEL +0 -0
- {aip_agents_binary-0.5.25b8.dist-info → aip_agents_binary-0.6.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from aip_agents.agent.hitl.manager import ApprovalManager as ApprovalManager
|
|
3
|
+
from aip_agents.schema.hitl import ApprovalDecision as ApprovalDecision, ApprovalRequest as ApprovalRequest
|
|
4
|
+
|
|
5
|
+
class BasePromptHandler(ABC):
|
|
6
|
+
"""Abstract base class for prompt handlers used in HITL flows."""
|
|
7
|
+
def attach_manager(self, manager: ApprovalManager) -> None:
|
|
8
|
+
"""Optionally attach the ``ApprovalManager`` coordinating approvals.
|
|
9
|
+
|
|
10
|
+
Args:
|
|
11
|
+
manager (ApprovalManager): The approval manager instance to attach.
|
|
12
|
+
"""
|
|
13
|
+
@abstractmethod
|
|
14
|
+
async def prompt_for_decision(self, request: ApprovalRequest, timeout_seconds: int, context_keys: list[str] | None = None) -> ApprovalDecision:
|
|
15
|
+
"""Collect and return a decision for the given approval request.
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
request (ApprovalRequest): The approval request to prompt for.
|
|
19
|
+
timeout_seconds (int): Maximum time to wait for a decision in seconds.
|
|
20
|
+
context_keys (list[str] | None, optional): Optional keys for additional context. Defaults to None.
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
ApprovalDecision: The decision made for the approval request.
|
|
24
|
+
"""
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from aip_agents.agent.hitl.manager import ApprovalManager as ApprovalManager
|
|
2
|
+
from aip_agents.agent.hitl.prompt.base import BasePromptHandler as BasePromptHandler
|
|
3
|
+
from aip_agents.schema.hitl import ApprovalDecision as ApprovalDecision, ApprovalDecisionType as ApprovalDecisionType, ApprovalRequest as ApprovalRequest
|
|
4
|
+
from collections.abc import Callable
|
|
5
|
+
|
|
6
|
+
class DeferredPromptHandler(BasePromptHandler):
|
|
7
|
+
"""Prompt handler that defers tool execution until an external decision is received."""
|
|
8
|
+
def __init__(self, notify: Callable[[ApprovalRequest], None] | None = None) -> None:
|
|
9
|
+
"""Initialize the deferred prompt handler.
|
|
10
|
+
|
|
11
|
+
Args:
|
|
12
|
+
notify: Optional callback function to notify when an approval request is made.
|
|
13
|
+
"""
|
|
14
|
+
def attach_manager(self, manager: ApprovalManager) -> None:
|
|
15
|
+
"""Attach the ApprovalManager orchestrating approvals.
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
manager: The ApprovalManager instance to attach for handling approval decisions.
|
|
19
|
+
"""
|
|
20
|
+
async def prompt_for_decision(self, request: ApprovalRequest, timeout_seconds: int, context_keys: list[str] | None = None) -> ApprovalDecision:
|
|
21
|
+
"""Register a waiter and return a pending decision sentinel.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
request: The approval request containing the tool call details and context.
|
|
25
|
+
timeout_seconds: Number of seconds to wait for approval before timing out.
|
|
26
|
+
context_keys: Optional list of context keys to include in the approval request.
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
ApprovalDecision with PENDING status and registered waiter for external resolution.
|
|
30
|
+
"""
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
from _typeshed import Incomplete
|
|
2
|
+
from aip_agents.agent.hitl.manager import ApprovalManager as ApprovalManager
|
|
3
|
+
|
|
4
|
+
class HITLManagerRegistry:
|
|
5
|
+
'''Global registry mapping request_id → owning ApprovalManager.
|
|
6
|
+
|
|
7
|
+
Uses weak references to avoid preventing manager garbage collection.
|
|
8
|
+
Thread-safe for concurrent agent execution.
|
|
9
|
+
|
|
10
|
+
This singleton registry allows the HITL decision endpoint to route decisions
|
|
11
|
+
to the correct manager in hierarchical agent setups, where a sub-agent may
|
|
12
|
+
create a pending request but the parent agent receives the decision.
|
|
13
|
+
|
|
14
|
+
Example:
|
|
15
|
+
>>> from aip_agents.agent.hitl.registry import hitl_registry
|
|
16
|
+
>>> # Manager auto-registers when creating requests
|
|
17
|
+
>>> manager.create_approval_request(...)
|
|
18
|
+
>>> # Later, decision handler looks up the owning manager
|
|
19
|
+
>>> owning_manager = hitl_registry.get_manager(request_id)
|
|
20
|
+
>>> owning_manager.resolve_pending_request(request_id, "approved")
|
|
21
|
+
'''
|
|
22
|
+
def __new__(cls) -> HITLManagerRegistry:
|
|
23
|
+
"""Ensure only one instance exists (singleton pattern).
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
The singleton HITLManagerRegistry instance.
|
|
27
|
+
"""
|
|
28
|
+
def register(self, request_id: str, manager: ApprovalManager) -> None:
|
|
29
|
+
'''Register a pending request with its owning manager.
|
|
30
|
+
|
|
31
|
+
This method is typically called automatically by ApprovalManager when
|
|
32
|
+
creating a new pending request. It establishes the ownership mapping
|
|
33
|
+
needed for proper decision routing.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
request_id: Unique identifier for the pending request
|
|
37
|
+
manager: ApprovalManager instance that owns this request
|
|
38
|
+
|
|
39
|
+
Example:
|
|
40
|
+
>>> hitl_registry.register("req_abc123", my_manager)
|
|
41
|
+
'''
|
|
42
|
+
def unregister(self, request_id: str) -> None:
|
|
43
|
+
'''Remove a request from the registry.
|
|
44
|
+
|
|
45
|
+
This method is called when a request is resolved, times out, or expires.
|
|
46
|
+
It\'s important for cleanup to prevent the registry from growing unbounded.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
request_id: Unique identifier to remove
|
|
50
|
+
|
|
51
|
+
Example:
|
|
52
|
+
>>> hitl_registry.unregister("req_abc123")
|
|
53
|
+
'''
|
|
54
|
+
def get_manager(self, request_id: str) -> ApprovalManager | None:
|
|
55
|
+
'''Retrieve the manager owning a specific request.
|
|
56
|
+
|
|
57
|
+
This is the primary lookup method used by decision handlers to route
|
|
58
|
+
decisions to the correct manager in hierarchical agent setups.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
request_id: Unique identifier to lookup
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
ApprovalManager instance if found, None otherwise. None can indicate
|
|
65
|
+
the request was resolved, timed out, or the manager was garbage collected.
|
|
66
|
+
|
|
67
|
+
Example:
|
|
68
|
+
>>> manager = hitl_registry.get_manager("req_abc123")
|
|
69
|
+
>>> if manager:
|
|
70
|
+
... manager.resolve_pending_request("req_abc123", "approved")
|
|
71
|
+
'''
|
|
72
|
+
def clear(self) -> None:
|
|
73
|
+
"""Clear all registrations.
|
|
74
|
+
|
|
75
|
+
This method is primarily intended for testing to ensure a clean state
|
|
76
|
+
between test cases. It removes all registered mappings.
|
|
77
|
+
|
|
78
|
+
Warning:
|
|
79
|
+
This should not be called in production code as it will prevent
|
|
80
|
+
pending requests from being resolved.
|
|
81
|
+
|
|
82
|
+
Example:
|
|
83
|
+
>>> hitl_registry.clear() # For testing only
|
|
84
|
+
"""
|
|
85
|
+
def list_all(self) -> list[str]:
|
|
86
|
+
'''List all currently registered request IDs.
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
List of request IDs currently in the registry.
|
|
90
|
+
|
|
91
|
+
Note:
|
|
92
|
+
Due to weak references, managers may be garbage collected between
|
|
93
|
+
calling this method and accessing them, so the actual available
|
|
94
|
+
managers might be fewer than the returned list length.
|
|
95
|
+
|
|
96
|
+
Example:
|
|
97
|
+
>>> request_ids = hitl_registry.list_all()
|
|
98
|
+
>>> print(f"Pending requests: {request_ids}")
|
|
99
|
+
'''
|
|
100
|
+
|
|
101
|
+
hitl_registry: Incomplete
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
from a2a.types import AgentCard as AgentCard
|
|
2
|
+
from abc import ABC, abstractmethod
|
|
3
|
+
from aip_agents.schema.agent import BaseAgentConfig as BaseAgentConfig
|
|
4
|
+
from collections.abc import AsyncGenerator
|
|
5
|
+
from gllm_inference.lm_invoker.lm_invoker import BaseLMInvoker
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
class AgentInterface(ABC):
|
|
9
|
+
"""A general and minimal interface for agent implementations.
|
|
10
|
+
|
|
11
|
+
Defines core execution methods (`__init__`, `run`, `arun`, `arun_stream`).
|
|
12
|
+
Concrete subclasses must implement all abstract methods.
|
|
13
|
+
"""
|
|
14
|
+
name: str
|
|
15
|
+
instruction: str
|
|
16
|
+
description: str | None
|
|
17
|
+
mcp_config: dict[str, Any]
|
|
18
|
+
lm_invoker: BaseLMInvoker | None
|
|
19
|
+
config: BaseAgentConfig | None
|
|
20
|
+
def __init__(self, name: str, instruction: str, description: str | None = None, lm_invoker: BaseLMInvoker | None = None, config: BaseAgentConfig | None = None, **kwargs: Any) -> None:
|
|
21
|
+
"""Initializes the agent.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
name: The name of the agent.
|
|
25
|
+
instruction: The core directive or system prompt for the agent.
|
|
26
|
+
description: Human-readable description. Defaults to instruction if not provided.
|
|
27
|
+
lm_invoker: The language model invoker to use for LLM interactions. Defaults to None.
|
|
28
|
+
config: Additional configuration for the agent.
|
|
29
|
+
**kwargs: Additional keyword arguments for concrete implementations.
|
|
30
|
+
"""
|
|
31
|
+
@abstractmethod
|
|
32
|
+
def run(self, query: str, **kwargs: Any) -> dict[str, Any]:
|
|
33
|
+
"""Synchronously runs the agent.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
query: The input query for the agent.
|
|
37
|
+
**kwargs: Additional keyword arguments for execution.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
Dict containing at least {'output': ...}.
|
|
41
|
+
"""
|
|
42
|
+
@abstractmethod
|
|
43
|
+
async def arun(self, query: str, **kwargs: Any) -> dict[str, Any]:
|
|
44
|
+
"""Asynchronously runs the agent.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
query: The input query for the agent.
|
|
48
|
+
**kwargs: Additional keyword arguments for execution.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
Dict containing at least {'output': ...}.
|
|
52
|
+
"""
|
|
53
|
+
@abstractmethod
|
|
54
|
+
async def arun_stream(self, query: str, **kwargs: Any) -> AsyncGenerator[str | dict[str, Any], None]:
|
|
55
|
+
"""Asynchronously streams the agent's response.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
query: The input query.
|
|
59
|
+
**kwargs: Extra parameters for execution.
|
|
60
|
+
|
|
61
|
+
Yields:
|
|
62
|
+
Chunks of output (strings or dicts).
|
|
63
|
+
"""
|
|
64
|
+
@abstractmethod
|
|
65
|
+
def add_mcp_server(self, mcp_config: dict[str, dict[str, Any]]) -> None:
|
|
66
|
+
"""Adds a new MCP server configuration.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
mcp_config: Dictionary containing server name as key and its configuration as value.
|
|
70
|
+
|
|
71
|
+
Raises:
|
|
72
|
+
ValueError: If mcp_config is empty or None, or if any server configuration is invalid.
|
|
73
|
+
KeyError: If any server name already exists in the configuration.
|
|
74
|
+
"""
|
|
75
|
+
@abstractmethod
|
|
76
|
+
def register_a2a_agents(self, agents: list[AgentCard]):
|
|
77
|
+
"""Registers A2A agents from a list of AgentCards.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
agents: A list of AgentCard instances.
|
|
81
|
+
"""
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from collections.abc import AsyncIterator
|
|
2
|
+
from typing import Any, Protocol
|
|
3
|
+
|
|
4
|
+
class LangGraphAgentProtocol(Protocol):
|
|
5
|
+
"""Minimal interface required by LangGraphA2AExecutor."""
|
|
6
|
+
name: str
|
|
7
|
+
async def arun_a2a_stream(self, query: str, **kwargs: Any) -> AsyncIterator[dict[str, Any]]:
|
|
8
|
+
"""Stream A2A-compatible chunks for the given query.
|
|
9
|
+
|
|
10
|
+
Args:
|
|
11
|
+
query (str): The query to execute and stream.
|
|
12
|
+
**kwargs (Any): Additional keyword arguments for execution.
|
|
13
|
+
|
|
14
|
+
Yields:
|
|
15
|
+
dict[str, Any]: A2A-compatible streaming chunks.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
class LangflowAgentProtocol(Protocol):
|
|
19
|
+
"""Minimal interface required by LangflowA2AExecutor."""
|
|
20
|
+
name: str
|
|
21
|
+
async def arun_a2a_stream(self, query: str, **kwargs: Any) -> AsyncIterator[dict[str, Any]]:
|
|
22
|
+
"""Stream A2A-compatible chunks for the given query.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
query (str): The query to execute and stream.
|
|
26
|
+
**kwargs (Any): Additional keyword arguments for execution.
|
|
27
|
+
|
|
28
|
+
Yields:
|
|
29
|
+
dict[str, Any]: A2A-compatible streaming chunks.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
class GoogleADKAgentProtocol(Protocol):
|
|
33
|
+
"""Minimal interface required by GoogleADKExecutor."""
|
|
34
|
+
name: str
|
|
35
|
+
async def arun_a2a_stream(self, query: str, **kwargs: Any) -> AsyncIterator[dict[str, Any]]:
|
|
36
|
+
"""Stream A2A-compatible chunks for the given query.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
query (str): The query to execute and stream.
|
|
40
|
+
**kwargs (Any): Additional keyword arguments for execution.
|
|
41
|
+
|
|
42
|
+
Yields:
|
|
43
|
+
dict[str, Any]: A2A-compatible streaming chunks.
|
|
44
|
+
"""
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
from _typeshed import Incomplete
|
|
2
|
+
from a2a.types import AgentCard as AgentCard
|
|
3
|
+
from aip_agents.agent.base_agent import BaseAgent as BaseAgent
|
|
4
|
+
from aip_agents.clients.langflow import LangflowApiClient as LangflowApiClient
|
|
5
|
+
from aip_agents.clients.langflow.types import LangflowEventType as LangflowEventType
|
|
6
|
+
from aip_agents.schema.agent import LangflowAgentConfig as LangflowAgentConfig
|
|
7
|
+
from aip_agents.types import A2AEvent as A2AEvent, A2AStreamEventType as A2AStreamEventType
|
|
8
|
+
from aip_agents.utils.logger import get_logger as get_logger
|
|
9
|
+
from aip_agents.utils.sse_chunk_transformer import SSEChunkTransformer as SSEChunkTransformer
|
|
10
|
+
from collections.abc import AsyncGenerator
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
logger: Incomplete
|
|
14
|
+
|
|
15
|
+
class LangflowAgent(BaseAgent):
|
|
16
|
+
"""Langflow agent implementation for executing Langflow flows.
|
|
17
|
+
|
|
18
|
+
This agent integrates with Langflow APIs to execute flows while providing
|
|
19
|
+
full compatibility with the SDK's agent framework, including:
|
|
20
|
+
- Synchronous and asynchronous execution
|
|
21
|
+
- Regular and A2A streaming support
|
|
22
|
+
- Session management for conversation continuity
|
|
23
|
+
- Error handling and retry logic
|
|
24
|
+
- Credential management through BaseAgent
|
|
25
|
+
|
|
26
|
+
The agent builds on BaseAgent to gain shared A2A utilities while focusing on
|
|
27
|
+
Langflow-specific execution logic.
|
|
28
|
+
"""
|
|
29
|
+
langflow_config: Incomplete
|
|
30
|
+
flow_id: Incomplete
|
|
31
|
+
api_client: Incomplete
|
|
32
|
+
def __init__(self, name: str, flow_id: str, description: str | None = None, base_url: str | None = None, api_key: str | None = None, config: LangflowAgentConfig | dict[str, Any] | None = None, **kwargs: Any) -> None:
|
|
33
|
+
"""Initialize the LangflowAgent.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
name: The name of the agent.
|
|
37
|
+
flow_id: The unique identifier of the Langflow flow to execute.
|
|
38
|
+
description: Human-readable description.
|
|
39
|
+
base_url: The base URL of the Langflow API server.
|
|
40
|
+
api_key: The API key for Langflow authentication.
|
|
41
|
+
config: Langflow-specific configuration or dict.
|
|
42
|
+
**kwargs: Additional keyword arguments passed to BaseAgent.
|
|
43
|
+
"""
|
|
44
|
+
def run(self, query: str, **kwargs: Any) -> dict[str, Any]:
|
|
45
|
+
"""Synchronously run the Langflow agent.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
query: The input query for the agent.
|
|
49
|
+
**kwargs: Additional keyword arguments.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
Dictionary containing the agent's response.
|
|
53
|
+
"""
|
|
54
|
+
async def arun(self, query: str, **kwargs: Any) -> dict[str, Any]:
|
|
55
|
+
"""Asynchronously run the Langflow agent.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
query: The input query for the agent.
|
|
59
|
+
**kwargs: Additional keyword arguments.
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
Dictionary containing the agent's response and metadata.
|
|
63
|
+
"""
|
|
64
|
+
async def arun_stream(self, query: str, **kwargs: Any) -> AsyncGenerator[str | dict[str, Any], None]:
|
|
65
|
+
"""Asynchronously stream the Langflow agent's response.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
query: The input query for the agent.
|
|
69
|
+
**kwargs: Additional keyword arguments.
|
|
70
|
+
|
|
71
|
+
Yields:
|
|
72
|
+
Chunks of output (strings or dicts) from the streaming response.
|
|
73
|
+
"""
|
|
74
|
+
async def arun_a2a_stream(self, query: str, **kwargs: Any) -> AsyncGenerator[dict[str, Any], None]:
|
|
75
|
+
"""Asynchronously stream the agent's response in A2A format.
|
|
76
|
+
|
|
77
|
+
This method converts Langflow streaming events into A2A-compatible events
|
|
78
|
+
following the patterns established by BaseLangGraphAgent.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
query: The input query for the agent.
|
|
82
|
+
**kwargs: Additional keyword arguments.
|
|
83
|
+
|
|
84
|
+
Yields:
|
|
85
|
+
A2A-compatible event dictionaries with semantic event types.
|
|
86
|
+
"""
|
|
87
|
+
async def arun_sse_stream(self, query: str, task_id: str | None = None, context_id: str | None = None, **kwargs: Any) -> AsyncGenerator[dict[str, Any], None]:
|
|
88
|
+
'''Stream agent response as SSE-compatible chunks.
|
|
89
|
+
|
|
90
|
+
This method wraps arun_a2a_stream and transforms output to the normalized
|
|
91
|
+
dict format matching A2AConnector.astream_to_agent output, enabling direct
|
|
92
|
+
streaming without A2A server overhead.
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
query: The input query for the agent.
|
|
96
|
+
task_id: Optional task identifier for the stream.
|
|
97
|
+
context_id: Optional context identifier for the stream.
|
|
98
|
+
**kwargs: Additional arguments passed to arun_a2a_stream.
|
|
99
|
+
|
|
100
|
+
Yields:
|
|
101
|
+
SSEChunk dicts with normalized structure:
|
|
102
|
+
- status: "success" | "error"
|
|
103
|
+
- task_state: "working" | "completed" | "failed" | "canceled"
|
|
104
|
+
- content: Text content or None
|
|
105
|
+
- event_type: Always string (never enum)
|
|
106
|
+
- final: True for terminal events
|
|
107
|
+
- metadata: Normalized metadata dict
|
|
108
|
+
- artifacts: Only present when non-empty
|
|
109
|
+
'''
|
|
110
|
+
def register_a2a_agents(self, agents: list[AgentCard]) -> None:
|
|
111
|
+
"""Register A2A agents (not supported for Langflow agents).
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
agents: List of AgentCard instances.
|
|
115
|
+
|
|
116
|
+
Raises:
|
|
117
|
+
NotImplementedError: Langflow agents don't support A2A agent registration.
|
|
118
|
+
"""
|
|
119
|
+
def add_mcp_server(self, mcp_config: dict[str, dict[str, Any]]) -> None:
|
|
120
|
+
"""Add MCP server configuration (not supported for Langflow agents).
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
mcp_config: MCP server configuration.
|
|
124
|
+
|
|
125
|
+
Raises:
|
|
126
|
+
NotImplementedError: Langflow agents don't support MCP servers.
|
|
127
|
+
"""
|
|
128
|
+
async def health_check(self) -> bool:
|
|
129
|
+
"""Check if the Langflow API is accessible.
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
True if the API is accessible, False otherwise.
|
|
133
|
+
"""
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from _typeshed import Incomplete
|
|
2
|
+
from aip_agents.agent.langgraph_react_agent import LangGraphReactAgent as LangGraphReactAgent
|
|
3
|
+
from aip_agents.agent.system_instruction_context import get_current_date_context as get_current_date_context
|
|
4
|
+
from aip_agents.memory.guidance import MEM0_MEMORY_RECALL_GUIDANCE as MEM0_MEMORY_RECALL_GUIDANCE
|
|
5
|
+
from aip_agents.tools.memory_search_tool import LongTermMemorySearchTool as LongTermMemorySearchTool, MEMORY_SEARCH_TOOL_NAME as MEMORY_SEARCH_TOOL_NAME, Mem0SearchTool as Mem0SearchTool
|
|
6
|
+
from aip_agents.utils.logger import get_logger as get_logger
|
|
7
|
+
from langgraph.graph import StateGraph
|
|
8
|
+
from langgraph.graph.state import CompiledStateGraph
|
|
9
|
+
|
|
10
|
+
logger: Incomplete
|
|
11
|
+
|
|
12
|
+
class LangGraphMemoryEnhancerAgent(LangGraphReactAgent):
|
|
13
|
+
"""Simplified mini-agent for automatic memory retrieval and query enhancement.
|
|
14
|
+
|
|
15
|
+
This agent has a simple 2-node LangGraph (agent + tools) and uses existing memory
|
|
16
|
+
infrastructure to enhance user queries with relevant context. It acts as a
|
|
17
|
+
preprocessing layer that automatically attempts memory retrieval for every query.
|
|
18
|
+
|
|
19
|
+
Key features:
|
|
20
|
+
- Uses runtime `memory_user_id` provided via call arguments (no static storage)
|
|
21
|
+
- Uses simplified instruction reusing existing guidance
|
|
22
|
+
- Standard 2-node LangGraph pattern (agent -> tools -> agent)
|
|
23
|
+
- Automatically enhances queries with memory context when available
|
|
24
|
+
- Returns original query unchanged if no relevant memories found
|
|
25
|
+
"""
|
|
26
|
+
def __init__(self, memory, **kwargs) -> None:
|
|
27
|
+
"""Initialize the LangGraphMemoryEnhancerAgent with memory backend and configuration.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
memory: Memory backend instance (Mem0Memory or compatible)
|
|
31
|
+
**kwargs: Additional arguments passed to BaseLangGraphAgent, including:
|
|
32
|
+
- memory_agent_id: Fallback user ID for memory operations
|
|
33
|
+
- model: LLM model to use for memory decisions
|
|
34
|
+
- Other BaseLangGraphAgent parameters
|
|
35
|
+
"""
|
|
36
|
+
def define_graph(self, graph_builder: StateGraph) -> CompiledStateGraph:
|
|
37
|
+
"""Define the 3-node memory recall LangGraph for this agent.
|
|
38
|
+
|
|
39
|
+
This creates a streamlined ReAct-inspired structure that reuses
|
|
40
|
+
`LangGraphReactAgent` helpers for robust LM invocation, token usage tracking,
|
|
41
|
+
error handling, and tool execution.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
graph_builder: LangGraph `StateGraph` builder instance used to register nodes and
|
|
45
|
+
edges for compilation.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
CompiledStateGraph: The compiled memory recall graph ready for execution.
|
|
49
|
+
"""
|
|
@@ -18,14 +18,14 @@ from collections.abc import Awaitable, Callable, Sequence
|
|
|
18
18
|
from dataclasses import asdict, dataclass
|
|
19
19
|
from functools import reduce
|
|
20
20
|
from textwrap import dedent
|
|
21
|
-
from typing import TYPE_CHECKING, Annotated, Any
|
|
21
|
+
from typing import TYPE_CHECKING, Annotated, Any, cast
|
|
22
22
|
|
|
23
|
-
from deprecated import deprecated
|
|
23
|
+
from deprecated import deprecated # type: ignore[import-untyped]
|
|
24
24
|
|
|
25
25
|
if TYPE_CHECKING:
|
|
26
26
|
from aip_agents.guardrails.manager import GuardrailManager
|
|
27
|
-
from gllm_core.event import EventEmitter
|
|
28
|
-
from gllm_core.schema import Chunk
|
|
27
|
+
from gllm_core.event import EventEmitter # type: ignore[import-untyped]
|
|
28
|
+
from gllm_core.schema import Chunk # type: ignore[import-untyped]
|
|
29
29
|
from langchain_core.language_models import BaseChatModel
|
|
30
30
|
from langchain_core.messages import (
|
|
31
31
|
AIMessage,
|
|
@@ -212,6 +212,12 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
212
212
|
**kwargs,
|
|
213
213
|
)
|
|
214
214
|
|
|
215
|
+
if self.model is None and self.lm_invoker is None:
|
|
216
|
+
logger.warning(
|
|
217
|
+
"Agent '%s': Model and LM invoker are both unset. Calls that require a model will fail.",
|
|
218
|
+
self.name,
|
|
219
|
+
)
|
|
220
|
+
|
|
215
221
|
# Handle tool output management
|
|
216
222
|
self.tool_output_manager = tool_output_manager
|
|
217
223
|
self._pii_handlers_by_thread: dict[str, ToolPIIHandler] = {}
|
|
@@ -256,7 +262,7 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
256
262
|
|
|
257
263
|
# Auto-configure TodoListMiddleware if planning enabled
|
|
258
264
|
if planning:
|
|
259
|
-
middleware_list.append(TodoListMiddleware())
|
|
265
|
+
middleware_list.append(cast(AgentMiddleware, TodoListMiddleware()))
|
|
260
266
|
|
|
261
267
|
# Auto-configure GuardrailMiddleware if guardrail provided
|
|
262
268
|
if guardrail:
|
|
@@ -732,7 +738,7 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
732
738
|
pending_artifacts: list[dict[str, Any]] = state.get("artifacts") or []
|
|
733
739
|
reference_updates: list[Chunk] = []
|
|
734
740
|
tool_map = {tool.name: tool for tool in self.resolved_tools}
|
|
735
|
-
pii_mapping = {}
|
|
741
|
+
pii_mapping: dict[str, str] = {}
|
|
736
742
|
|
|
737
743
|
aggregated_metadata_delta: dict[str, Any] = {}
|
|
738
744
|
total_tools_token_usage: list[UsageMetadata] = []
|
|
@@ -756,7 +762,8 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
756
762
|
),
|
|
757
763
|
)
|
|
758
764
|
|
|
759
|
-
|
|
765
|
+
normalized_tool_calls = [self._normalize_tool_call(tc) for tc in last_message.tool_calls]
|
|
766
|
+
tasks = [asyncio.create_task(run_tool(tc)) for tc in normalized_tool_calls]
|
|
760
767
|
|
|
761
768
|
for coro in asyncio.as_completed(tasks):
|
|
762
769
|
tool_result = await coro
|
|
@@ -779,6 +786,31 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
779
786
|
pii_mapping,
|
|
780
787
|
)
|
|
781
788
|
|
|
789
|
+
def _normalize_tool_call(self, tool_call: Any) -> dict[str, Any]:
|
|
790
|
+
"""Normalize tool call inputs into a dict with required keys."""
|
|
791
|
+
if isinstance(tool_call, dict):
|
|
792
|
+
normalized = dict(tool_call)
|
|
793
|
+
elif hasattr(tool_call, "model_dump"):
|
|
794
|
+
normalized = tool_call.model_dump()
|
|
795
|
+
elif hasattr(tool_call, "dict"):
|
|
796
|
+
normalized = tool_call.dict()
|
|
797
|
+
elif hasattr(tool_call, "name") and hasattr(tool_call, "args"):
|
|
798
|
+
normalized = {
|
|
799
|
+
"id": getattr(tool_call, "id", None),
|
|
800
|
+
"name": getattr(tool_call, "name", None),
|
|
801
|
+
"args": getattr(tool_call, "args", None),
|
|
802
|
+
}
|
|
803
|
+
else:
|
|
804
|
+
raise TypeError("Tool call must be a dict-like object or ToolCall instance.")
|
|
805
|
+
|
|
806
|
+
if not isinstance(normalized, dict):
|
|
807
|
+
raise TypeError("Tool call normalization did not produce a dict.")
|
|
808
|
+
|
|
809
|
+
if "name" not in normalized or "args" not in normalized:
|
|
810
|
+
raise TypeError("Tool call must include 'name' and 'args' fields.")
|
|
811
|
+
|
|
812
|
+
return normalized
|
|
813
|
+
|
|
782
814
|
def _accumulate_tool_result( # noqa: PLR0913
|
|
783
815
|
self,
|
|
784
816
|
tool_result: Any,
|
|
@@ -787,7 +819,7 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
787
819
|
aggregated_metadata_delta: dict[str, Any],
|
|
788
820
|
reference_updates: list[Chunk],
|
|
789
821
|
total_tools_token_usage: list[UsageMetadata],
|
|
790
|
-
pii_mapping: dict[str, str]
|
|
822
|
+
pii_mapping: dict[str, str],
|
|
791
823
|
) -> None: # noqa: PLR0913
|
|
792
824
|
"""Accumulate results from a single tool call.
|
|
793
825
|
|
|
@@ -1233,13 +1265,16 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
1233
1265
|
|
|
1234
1266
|
# Create enhanced tool configuration with output management
|
|
1235
1267
|
tool_config = self._create_enhanced_tool_config(config, state, tool_call["name"], tool_call_id)
|
|
1268
|
+
if not isinstance(tool_config, dict):
|
|
1269
|
+
raise TypeError("Tool configuration must be a dictionary.")
|
|
1270
|
+
tool_config_runnable = tool_config
|
|
1236
1271
|
|
|
1237
1272
|
arun_streaming_method = getattr(tool, TOOL_RUN_STREAMING_METHOD, None)
|
|
1238
1273
|
|
|
1239
1274
|
if arun_streaming_method and callable(arun_streaming_method):
|
|
1240
1275
|
tool_output = await self._execute_tool_with_streaming(tool, tool_call, tool_config)
|
|
1241
1276
|
else:
|
|
1242
|
-
tool_output = await tool.ainvoke(resolved_args,
|
|
1277
|
+
tool_output = await tool.ainvoke(resolved_args, tool_config_runnable)
|
|
1243
1278
|
|
|
1244
1279
|
references = extract_references_from_tool(tool, tool_output)
|
|
1245
1280
|
|
|
@@ -1513,7 +1548,7 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
1513
1548
|
tool_call: dict[str, Any],
|
|
1514
1549
|
execution_time: float,
|
|
1515
1550
|
pending_artifacts: list[dict[str, Any]],
|
|
1516
|
-
) -> tuple[list[
|
|
1551
|
+
) -> tuple[list[ToolMessage], list[dict[str, Any]], dict[str, Any]]:
|
|
1517
1552
|
"""Process tool output into messages, artifacts, and metadata.
|
|
1518
1553
|
|
|
1519
1554
|
Args:
|
|
@@ -1541,7 +1576,7 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
1541
1576
|
|
|
1542
1577
|
def _handle_command_output(
|
|
1543
1578
|
self, tool_output: Command, tool_call: dict[str, Any], execution_time: float, metadata_delta: dict[str, Any]
|
|
1544
|
-
) -> tuple[list[
|
|
1579
|
+
) -> tuple[list[ToolMessage], list[dict[str, Any]], dict[str, Any]]:
|
|
1545
1580
|
"""Handle Command type tool outputs.
|
|
1546
1581
|
|
|
1547
1582
|
Args:
|
|
@@ -1570,7 +1605,7 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
1570
1605
|
|
|
1571
1606
|
def _handle_string_output(
|
|
1572
1607
|
self, tool_output: str, tool_call: dict[str, Any], execution_time: float
|
|
1573
|
-
) -> tuple[list[
|
|
1608
|
+
) -> tuple[list[ToolMessage], list[dict[str, Any]], dict[str, Any]]:
|
|
1574
1609
|
"""Handle string type tool outputs.
|
|
1575
1610
|
|
|
1576
1611
|
Args:
|
|
@@ -1596,7 +1631,7 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
1596
1631
|
execution_time: float,
|
|
1597
1632
|
pending_artifacts: list[dict[str, Any]],
|
|
1598
1633
|
metadata_delta: dict[str, Any],
|
|
1599
|
-
) -> tuple[list[
|
|
1634
|
+
) -> tuple[list[ToolMessage], list[dict[str, Any]], dict[str, Any]]:
|
|
1600
1635
|
"""Handle legacy dict and other tool outputs.
|
|
1601
1636
|
|
|
1602
1637
|
Args:
|
|
@@ -1694,8 +1729,11 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
1694
1729
|
self._emit_default_tool_call_event(writer, tool_name, tool_call_id, tool_args)
|
|
1695
1730
|
|
|
1696
1731
|
streaming_kwargs = self._build_streaming_kwargs(tool_args, tool_config)
|
|
1732
|
+
arun_streaming_method = getattr(tool, TOOL_RUN_STREAMING_METHOD, None)
|
|
1733
|
+
if not callable(arun_streaming_method):
|
|
1734
|
+
raise RuntimeError(f"Tool '{tool_name}' does not implement streaming.")
|
|
1697
1735
|
|
|
1698
|
-
async for chunk in
|
|
1736
|
+
async for chunk in arun_streaming_method(**streaming_kwargs):
|
|
1699
1737
|
final_output, saw_tool_result = self._handle_streaming_chunk(
|
|
1700
1738
|
chunk=chunk,
|
|
1701
1739
|
writer=writer,
|
|
@@ -2125,6 +2163,9 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
2125
2163
|
|
|
2126
2164
|
effective_event_emitter = state.get("event_emitter") or self.event_emitter
|
|
2127
2165
|
|
|
2166
|
+
if self.lm_invoker is None:
|
|
2167
|
+
raise RuntimeError("LM invoker is required for this execution path.")
|
|
2168
|
+
|
|
2128
2169
|
if self.resolved_tools:
|
|
2129
2170
|
self.lm_invoker.set_tools(self.resolved_tools)
|
|
2130
2171
|
|
|
@@ -2183,6 +2224,9 @@ class LangGraphReactAgent(LangGraphHitLMixin, BaseLangGraphAgent):
|
|
|
2183
2224
|
):
|
|
2184
2225
|
langchain_prompt = [SystemMessage(content=enhanced_instruction)] + list(current_messages)
|
|
2185
2226
|
|
|
2227
|
+
if self.model is None:
|
|
2228
|
+
raise RuntimeError("Model is required for this execution path.")
|
|
2229
|
+
|
|
2186
2230
|
model_with_tools = self.model.bind_tools(self.resolved_tools) if self.resolved_tools else self.model
|
|
2187
2231
|
|
|
2188
2232
|
ai_message = await model_with_tools.ainvoke(langchain_prompt, config)
|