agentpool 2.1.9__py3-none-any.whl → 2.5.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.
- acp/__init__.py +13 -4
- acp/acp_requests.py +20 -77
- acp/agent/connection.py +8 -0
- acp/agent/implementations/debug_server/debug_server.py +6 -2
- acp/agent/protocol.py +6 -0
- acp/bridge/README.md +15 -2
- acp/bridge/__init__.py +3 -2
- acp/bridge/__main__.py +60 -19
- acp/bridge/ws_server.py +173 -0
- acp/bridge/ws_server_cli.py +89 -0
- acp/client/connection.py +38 -29
- acp/client/implementations/default_client.py +3 -2
- acp/client/implementations/headless_client.py +2 -2
- acp/connection.py +2 -2
- acp/notifications.py +20 -50
- acp/schema/__init__.py +2 -0
- acp/schema/agent_responses.py +21 -0
- acp/schema/client_requests.py +3 -3
- acp/schema/session_state.py +63 -29
- acp/stdio.py +39 -9
- acp/task/supervisor.py +2 -2
- acp/transports.py +362 -2
- acp/utils.py +17 -4
- agentpool/__init__.py +6 -1
- agentpool/agents/__init__.py +2 -0
- agentpool/agents/acp_agent/acp_agent.py +407 -277
- agentpool/agents/acp_agent/acp_converters.py +196 -38
- agentpool/agents/acp_agent/client_handler.py +191 -26
- agentpool/agents/acp_agent/session_state.py +17 -6
- agentpool/agents/agent.py +607 -572
- agentpool/agents/agui_agent/__init__.py +0 -2
- agentpool/agents/agui_agent/agui_agent.py +176 -110
- agentpool/agents/agui_agent/agui_converters.py +0 -131
- agentpool/agents/agui_agent/helpers.py +3 -4
- agentpool/agents/base_agent.py +632 -17
- agentpool/agents/claude_code_agent/FORKING.md +191 -0
- agentpool/agents/claude_code_agent/__init__.py +13 -1
- agentpool/agents/claude_code_agent/claude_code_agent.py +1058 -291
- agentpool/agents/claude_code_agent/converters.py +74 -143
- agentpool/agents/claude_code_agent/history.py +474 -0
- agentpool/agents/claude_code_agent/models.py +77 -0
- agentpool/agents/claude_code_agent/static_info.py +100 -0
- agentpool/agents/claude_code_agent/usage.py +242 -0
- agentpool/agents/context.py +40 -0
- agentpool/agents/events/__init__.py +24 -0
- agentpool/agents/events/builtin_handlers.py +67 -1
- agentpool/agents/events/event_emitter.py +32 -2
- agentpool/agents/events/events.py +104 -3
- agentpool/agents/events/infer_info.py +145 -0
- agentpool/agents/events/processors.py +254 -0
- agentpool/agents/interactions.py +41 -6
- agentpool/agents/modes.py +67 -0
- agentpool/agents/slashed_agent.py +5 -4
- agentpool/agents/tool_call_accumulator.py +213 -0
- agentpool/agents/tool_wrapping.py +18 -6
- agentpool/common_types.py +56 -21
- agentpool/config_resources/__init__.py +38 -1
- agentpool/config_resources/acp_assistant.yml +2 -2
- agentpool/config_resources/agents.yml +3 -0
- agentpool/config_resources/agents_template.yml +1 -0
- agentpool/config_resources/claude_code_agent.yml +10 -6
- agentpool/config_resources/external_acp_agents.yml +2 -1
- agentpool/delegation/base_team.py +4 -30
- agentpool/delegation/pool.py +136 -289
- agentpool/delegation/team.py +58 -57
- agentpool/delegation/teamrun.py +51 -55
- agentpool/diagnostics/__init__.py +53 -0
- agentpool/diagnostics/lsp_manager.py +1593 -0
- agentpool/diagnostics/lsp_proxy.py +41 -0
- agentpool/diagnostics/lsp_proxy_script.py +229 -0
- agentpool/diagnostics/models.py +398 -0
- agentpool/functional/run.py +10 -4
- agentpool/mcp_server/__init__.py +0 -2
- agentpool/mcp_server/client.py +76 -32
- agentpool/mcp_server/conversions.py +54 -13
- agentpool/mcp_server/manager.py +34 -54
- agentpool/mcp_server/registries/official_registry_client.py +35 -1
- agentpool/mcp_server/tool_bridge.py +186 -139
- agentpool/messaging/__init__.py +0 -2
- agentpool/messaging/compaction.py +72 -197
- agentpool/messaging/connection_manager.py +11 -10
- agentpool/messaging/event_manager.py +5 -5
- agentpool/messaging/message_container.py +6 -30
- agentpool/messaging/message_history.py +99 -8
- agentpool/messaging/messagenode.py +52 -14
- agentpool/messaging/messages.py +54 -35
- agentpool/messaging/processing.py +12 -22
- agentpool/models/__init__.py +1 -1
- agentpool/models/acp_agents/base.py +6 -24
- agentpool/models/acp_agents/mcp_capable.py +126 -157
- agentpool/models/acp_agents/non_mcp.py +129 -95
- agentpool/models/agents.py +98 -76
- agentpool/models/agui_agents.py +1 -1
- agentpool/models/claude_code_agents.py +144 -19
- agentpool/models/file_parsing.py +0 -1
- agentpool/models/manifest.py +113 -50
- agentpool/prompts/conversion_manager.py +1 -1
- agentpool/prompts/prompts.py +5 -2
- agentpool/repomap.py +1 -1
- agentpool/resource_providers/__init__.py +11 -1
- agentpool/resource_providers/aggregating.py +56 -5
- agentpool/resource_providers/base.py +70 -4
- agentpool/resource_providers/codemode/code_executor.py +72 -5
- agentpool/resource_providers/codemode/helpers.py +2 -2
- agentpool/resource_providers/codemode/provider.py +64 -12
- agentpool/resource_providers/codemode/remote_mcp_execution.py +2 -2
- agentpool/resource_providers/codemode/remote_provider.py +9 -12
- agentpool/resource_providers/filtering.py +3 -1
- agentpool/resource_providers/mcp_provider.py +89 -12
- agentpool/resource_providers/plan_provider.py +228 -46
- agentpool/resource_providers/pool.py +7 -3
- agentpool/resource_providers/resource_info.py +111 -0
- agentpool/resource_providers/static.py +4 -2
- agentpool/sessions/__init__.py +4 -1
- agentpool/sessions/manager.py +33 -5
- agentpool/sessions/models.py +59 -6
- agentpool/sessions/protocol.py +28 -0
- agentpool/sessions/session.py +11 -55
- agentpool/skills/registry.py +13 -8
- agentpool/storage/manager.py +572 -49
- agentpool/talk/registry.py +4 -4
- agentpool/talk/talk.py +9 -10
- agentpool/testing.py +538 -20
- agentpool/tool_impls/__init__.py +6 -0
- agentpool/tool_impls/agent_cli/__init__.py +42 -0
- agentpool/tool_impls/agent_cli/tool.py +95 -0
- agentpool/tool_impls/bash/__init__.py +64 -0
- agentpool/tool_impls/bash/helpers.py +35 -0
- agentpool/tool_impls/bash/tool.py +171 -0
- agentpool/tool_impls/delete_path/__init__.py +70 -0
- agentpool/tool_impls/delete_path/tool.py +142 -0
- agentpool/tool_impls/download_file/__init__.py +80 -0
- agentpool/tool_impls/download_file/tool.py +183 -0
- agentpool/tool_impls/execute_code/__init__.py +55 -0
- agentpool/tool_impls/execute_code/tool.py +163 -0
- agentpool/tool_impls/grep/__init__.py +80 -0
- agentpool/tool_impls/grep/tool.py +200 -0
- agentpool/tool_impls/list_directory/__init__.py +73 -0
- agentpool/tool_impls/list_directory/tool.py +197 -0
- agentpool/tool_impls/question/__init__.py +42 -0
- agentpool/tool_impls/question/tool.py +127 -0
- agentpool/tool_impls/read/__init__.py +104 -0
- agentpool/tool_impls/read/tool.py +305 -0
- agentpool/tools/__init__.py +2 -1
- agentpool/tools/base.py +114 -34
- agentpool/tools/manager.py +57 -1
- agentpool/ui/base.py +2 -2
- agentpool/ui/mock_provider.py +2 -2
- agentpool/ui/stdlib_provider.py +2 -2
- agentpool/utils/file_watcher.py +269 -0
- agentpool/utils/identifiers.py +121 -0
- agentpool/utils/pydantic_ai_helpers.py +46 -0
- agentpool/utils/streams.py +616 -2
- agentpool/utils/subprocess_utils.py +155 -0
- agentpool/utils/token_breakdown.py +461 -0
- agentpool/vfs_registry.py +7 -2
- {agentpool-2.1.9.dist-info → agentpool-2.5.0.dist-info}/METADATA +41 -27
- agentpool-2.5.0.dist-info/RECORD +579 -0
- {agentpool-2.1.9.dist-info → agentpool-2.5.0.dist-info}/WHEEL +1 -1
- agentpool_cli/__main__.py +24 -0
- agentpool_cli/create.py +1 -1
- agentpool_cli/serve_acp.py +100 -21
- agentpool_cli/serve_agui.py +87 -0
- agentpool_cli/serve_opencode.py +119 -0
- agentpool_cli/ui.py +557 -0
- agentpool_commands/__init__.py +42 -5
- agentpool_commands/agents.py +75 -2
- agentpool_commands/history.py +62 -0
- agentpool_commands/mcp.py +176 -0
- agentpool_commands/models.py +56 -3
- agentpool_commands/pool.py +260 -0
- agentpool_commands/session.py +1 -1
- agentpool_commands/text_sharing/__init__.py +119 -0
- agentpool_commands/text_sharing/base.py +123 -0
- agentpool_commands/text_sharing/github_gist.py +80 -0
- agentpool_commands/text_sharing/opencode.py +462 -0
- agentpool_commands/text_sharing/paste_rs.py +59 -0
- agentpool_commands/text_sharing/pastebin.py +116 -0
- agentpool_commands/text_sharing/shittycodingagent.py +112 -0
- agentpool_commands/tools.py +57 -0
- agentpool_commands/utils.py +80 -30
- agentpool_config/__init__.py +30 -2
- agentpool_config/agentpool_tools.py +498 -0
- agentpool_config/builtin_tools.py +77 -22
- agentpool_config/commands.py +24 -1
- agentpool_config/compaction.py +258 -0
- agentpool_config/converters.py +1 -1
- agentpool_config/event_handlers.py +42 -0
- agentpool_config/events.py +1 -1
- agentpool_config/forward_targets.py +1 -4
- agentpool_config/jinja.py +3 -3
- agentpool_config/mcp_server.py +132 -6
- agentpool_config/nodes.py +1 -1
- agentpool_config/observability.py +44 -0
- agentpool_config/session.py +0 -3
- agentpool_config/storage.py +82 -38
- agentpool_config/task.py +3 -3
- agentpool_config/tools.py +11 -22
- agentpool_config/toolsets.py +109 -233
- agentpool_server/a2a_server/agent_worker.py +307 -0
- agentpool_server/a2a_server/server.py +23 -18
- agentpool_server/acp_server/acp_agent.py +234 -181
- agentpool_server/acp_server/commands/acp_commands.py +151 -156
- agentpool_server/acp_server/commands/docs_commands/fetch_repo.py +18 -17
- agentpool_server/acp_server/event_converter.py +651 -0
- agentpool_server/acp_server/input_provider.py +53 -10
- agentpool_server/acp_server/server.py +24 -90
- agentpool_server/acp_server/session.py +173 -331
- agentpool_server/acp_server/session_manager.py +8 -34
- agentpool_server/agui_server/server.py +3 -1
- agentpool_server/mcp_server/server.py +5 -2
- agentpool_server/opencode_server/.rules +95 -0
- agentpool_server/opencode_server/ENDPOINTS.md +401 -0
- agentpool_server/opencode_server/OPENCODE_UI_TOOLS_COMPLETE.md +202 -0
- agentpool_server/opencode_server/__init__.py +19 -0
- agentpool_server/opencode_server/command_validation.py +172 -0
- agentpool_server/opencode_server/converters.py +975 -0
- agentpool_server/opencode_server/dependencies.py +24 -0
- agentpool_server/opencode_server/input_provider.py +421 -0
- agentpool_server/opencode_server/models/__init__.py +250 -0
- agentpool_server/opencode_server/models/agent.py +53 -0
- agentpool_server/opencode_server/models/app.py +72 -0
- agentpool_server/opencode_server/models/base.py +26 -0
- agentpool_server/opencode_server/models/common.py +23 -0
- agentpool_server/opencode_server/models/config.py +37 -0
- agentpool_server/opencode_server/models/events.py +821 -0
- agentpool_server/opencode_server/models/file.py +88 -0
- agentpool_server/opencode_server/models/mcp.py +44 -0
- agentpool_server/opencode_server/models/message.py +179 -0
- agentpool_server/opencode_server/models/parts.py +323 -0
- agentpool_server/opencode_server/models/provider.py +81 -0
- agentpool_server/opencode_server/models/pty.py +43 -0
- agentpool_server/opencode_server/models/question.py +56 -0
- agentpool_server/opencode_server/models/session.py +111 -0
- agentpool_server/opencode_server/routes/__init__.py +29 -0
- agentpool_server/opencode_server/routes/agent_routes.py +473 -0
- agentpool_server/opencode_server/routes/app_routes.py +202 -0
- agentpool_server/opencode_server/routes/config_routes.py +302 -0
- agentpool_server/opencode_server/routes/file_routes.py +571 -0
- agentpool_server/opencode_server/routes/global_routes.py +94 -0
- agentpool_server/opencode_server/routes/lsp_routes.py +319 -0
- agentpool_server/opencode_server/routes/message_routes.py +761 -0
- agentpool_server/opencode_server/routes/permission_routes.py +63 -0
- agentpool_server/opencode_server/routes/pty_routes.py +300 -0
- agentpool_server/opencode_server/routes/question_routes.py +128 -0
- agentpool_server/opencode_server/routes/session_routes.py +1276 -0
- agentpool_server/opencode_server/routes/tui_routes.py +139 -0
- agentpool_server/opencode_server/server.py +475 -0
- agentpool_server/opencode_server/state.py +151 -0
- agentpool_server/opencode_server/time_utils.py +8 -0
- agentpool_storage/__init__.py +12 -0
- agentpool_storage/base.py +184 -2
- agentpool_storage/claude_provider/ARCHITECTURE.md +433 -0
- agentpool_storage/claude_provider/__init__.py +42 -0
- agentpool_storage/claude_provider/provider.py +1089 -0
- agentpool_storage/file_provider.py +278 -15
- agentpool_storage/memory_provider.py +193 -12
- agentpool_storage/models.py +3 -0
- agentpool_storage/opencode_provider/ARCHITECTURE.md +386 -0
- agentpool_storage/opencode_provider/__init__.py +16 -0
- agentpool_storage/opencode_provider/helpers.py +414 -0
- agentpool_storage/opencode_provider/provider.py +895 -0
- agentpool_storage/project_store.py +325 -0
- agentpool_storage/session_store.py +26 -6
- agentpool_storage/sql_provider/__init__.py +4 -2
- agentpool_storage/sql_provider/models.py +48 -0
- agentpool_storage/sql_provider/sql_provider.py +269 -3
- agentpool_storage/sql_provider/utils.py +12 -13
- agentpool_storage/zed_provider/__init__.py +16 -0
- agentpool_storage/zed_provider/helpers.py +281 -0
- agentpool_storage/zed_provider/models.py +130 -0
- agentpool_storage/zed_provider/provider.py +442 -0
- agentpool_storage/zed_provider.py +803 -0
- agentpool_toolsets/__init__.py +0 -2
- agentpool_toolsets/builtin/__init__.py +2 -12
- agentpool_toolsets/builtin/code.py +96 -57
- agentpool_toolsets/builtin/debug.py +118 -48
- agentpool_toolsets/builtin/execution_environment.py +115 -230
- agentpool_toolsets/builtin/file_edit/file_edit.py +115 -7
- agentpool_toolsets/builtin/skills.py +9 -4
- agentpool_toolsets/builtin/subagent_tools.py +64 -51
- agentpool_toolsets/builtin/workers.py +4 -2
- agentpool_toolsets/composio_toolset.py +2 -2
- agentpool_toolsets/entry_points.py +3 -1
- agentpool_toolsets/fsspec_toolset/__init__.py +13 -1
- agentpool_toolsets/fsspec_toolset/diagnostics.py +860 -73
- agentpool_toolsets/fsspec_toolset/grep.py +99 -7
- agentpool_toolsets/fsspec_toolset/helpers.py +3 -2
- agentpool_toolsets/fsspec_toolset/image_utils.py +161 -0
- agentpool_toolsets/fsspec_toolset/toolset.py +500 -95
- agentpool_toolsets/mcp_discovery/__init__.py +5 -0
- agentpool_toolsets/mcp_discovery/data/mcp_servers.parquet +0 -0
- agentpool_toolsets/mcp_discovery/toolset.py +511 -0
- agentpool_toolsets/mcp_run_toolset.py +87 -12
- agentpool_toolsets/notifications.py +33 -33
- agentpool_toolsets/openapi.py +3 -1
- agentpool_toolsets/search_toolset.py +3 -1
- agentpool-2.1.9.dist-info/RECORD +0 -474
- agentpool_config/resources.py +0 -33
- agentpool_server/acp_server/acp_tools.py +0 -43
- agentpool_server/acp_server/commands/spawn.py +0 -210
- agentpool_storage/text_log_provider.py +0 -275
- agentpool_toolsets/builtin/agent_management.py +0 -239
- agentpool_toolsets/builtin/chain.py +0 -288
- agentpool_toolsets/builtin/history.py +0 -36
- agentpool_toolsets/builtin/integration.py +0 -85
- agentpool_toolsets/builtin/tool_management.py +0 -90
- agentpool_toolsets/builtin/user_interaction.py +0 -52
- agentpool_toolsets/semantic_memory_toolset.py +0 -536
- {agentpool-2.1.9.dist-info → agentpool-2.5.0.dist-info}/entry_points.txt +0 -0
- {agentpool-2.1.9.dist-info → agentpool-2.5.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
"""Provider for agent pool building tools."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
from datetime import timedelta
|
|
6
|
-
from typing import TYPE_CHECKING, Any, Literal
|
|
7
|
-
|
|
8
|
-
import anyio
|
|
9
|
-
from pydantic_ai import ModelRetry
|
|
10
|
-
|
|
11
|
-
from agentpool.agents.context import AgentContext # noqa: TC001
|
|
12
|
-
from agentpool.log import get_logger
|
|
13
|
-
from agentpool.resource_providers import StaticResourceProvider
|
|
14
|
-
from agentpool.tools.exceptions import ToolError
|
|
15
|
-
from agentpool.utils.result_utils import to_type
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if TYPE_CHECKING:
|
|
19
|
-
from agentpool.agents import Agent
|
|
20
|
-
|
|
21
|
-
logger = get_logger(__name__)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
async def create_worker_agent[TDeps](
|
|
25
|
-
ctx: AgentContext[TDeps],
|
|
26
|
-
name: str,
|
|
27
|
-
system_prompt: str,
|
|
28
|
-
model: str | None = None,
|
|
29
|
-
) -> str:
|
|
30
|
-
"""Create a new agent and register it as a tool.
|
|
31
|
-
|
|
32
|
-
The new agent will be available as a tool for delegating specific tasks.
|
|
33
|
-
It inherits the current model unless overridden.
|
|
34
|
-
"""
|
|
35
|
-
from agentpool import Agent
|
|
36
|
-
|
|
37
|
-
if not ctx.pool:
|
|
38
|
-
msg = "Agent needs to be in a pool to list agents"
|
|
39
|
-
raise ToolError(msg)
|
|
40
|
-
|
|
41
|
-
model = model or ctx.agent.model_name
|
|
42
|
-
agent = Agent[TDeps](name=name, model=model, system_prompt=system_prompt, agent_pool=ctx.pool)
|
|
43
|
-
assert ctx.agent
|
|
44
|
-
tool_info = ctx.native_agent.register_worker(agent)
|
|
45
|
-
return f"Created worker agent and registered as tool: {tool_info.name}"
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
async def add_agent( # noqa: D417
|
|
49
|
-
ctx: AgentContext,
|
|
50
|
-
name: str,
|
|
51
|
-
system_prompt: str,
|
|
52
|
-
model: str | None = None,
|
|
53
|
-
tools: list[str] | None = None,
|
|
54
|
-
session: str | None = None,
|
|
55
|
-
output_type: str | None = None,
|
|
56
|
-
) -> str:
|
|
57
|
-
"""Add a new agent to the pool.
|
|
58
|
-
|
|
59
|
-
Args:
|
|
60
|
-
name: Name for the new agent
|
|
61
|
-
system_prompt: System prompt defining agent's role/behavior
|
|
62
|
-
model: Optional model override (uses default if not specified)
|
|
63
|
-
tools: Imort paths of the tools the agent should have, if any.
|
|
64
|
-
session: Session ID to recover conversation state from
|
|
65
|
-
output_type: Name of response type from manifest (for structured output)
|
|
66
|
-
|
|
67
|
-
Returns:
|
|
68
|
-
Confirmation message about the created agent
|
|
69
|
-
"""
|
|
70
|
-
assert ctx.pool, "No agent pool available"
|
|
71
|
-
try:
|
|
72
|
-
agent: Agent[Any, Any] = await ctx.pool.add_agent(
|
|
73
|
-
name=name,
|
|
74
|
-
system_prompt=system_prompt,
|
|
75
|
-
model=model,
|
|
76
|
-
tools=tools,
|
|
77
|
-
output_type=to_type(output_type, responses=ctx.pool.manifest.responses),
|
|
78
|
-
session=session,
|
|
79
|
-
)
|
|
80
|
-
except ValueError as e: # for wrong tool imports
|
|
81
|
-
raise ModelRetry(message=f"Error creating agent: {e}") from None
|
|
82
|
-
return f"Created agent **{agent.name}** using model **{agent.model_name}**"
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
async def add_team( # noqa: D417
|
|
86
|
-
ctx: AgentContext,
|
|
87
|
-
nodes: list[str],
|
|
88
|
-
mode: Literal["sequential", "parallel"] = "sequential",
|
|
89
|
-
name: str | None = None,
|
|
90
|
-
) -> str:
|
|
91
|
-
"""Create a team from existing agents.
|
|
92
|
-
|
|
93
|
-
Args:
|
|
94
|
-
nodes: Names of agents / sub-teams to include in team
|
|
95
|
-
mode: How the team should operate:
|
|
96
|
-
- sequential: Agents process in sequence (pipeline)
|
|
97
|
-
- parallel: Agents process simultaneously
|
|
98
|
-
name: Optional name for the team
|
|
99
|
-
"""
|
|
100
|
-
if not ctx.pool:
|
|
101
|
-
msg = "No agent pool available"
|
|
102
|
-
raise ToolError(msg)
|
|
103
|
-
|
|
104
|
-
# Verify all agents exist
|
|
105
|
-
for node_name in nodes:
|
|
106
|
-
if node_name not in ctx.pool.nodes:
|
|
107
|
-
msg = (
|
|
108
|
-
f"No agent or team found with name: {node_name}. "
|
|
109
|
-
f"Available nodes: {', '.join(ctx.pool.nodes.keys())}"
|
|
110
|
-
)
|
|
111
|
-
raise ModelRetry(msg)
|
|
112
|
-
if mode == "sequential":
|
|
113
|
-
ctx.pool.create_team_run(nodes, name=name)
|
|
114
|
-
else:
|
|
115
|
-
ctx.pool.create_team(nodes, name=name)
|
|
116
|
-
mode_str = "pipeline" if mode == "sequential" else "parallel"
|
|
117
|
-
return f"Created **{mode_str}** team with nodes: **{', '.join(nodes)}**"
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
async def connect_nodes( # noqa: D417
|
|
121
|
-
ctx: AgentContext,
|
|
122
|
-
source: str,
|
|
123
|
-
target: str,
|
|
124
|
-
*,
|
|
125
|
-
connection_type: Literal["run", "context", "forward"] = "run",
|
|
126
|
-
priority: int = 0,
|
|
127
|
-
delay_seconds: float | None = None,
|
|
128
|
-
queued: bool = False,
|
|
129
|
-
queue_strategy: Literal["concat", "latest", "buffer"] = "latest",
|
|
130
|
-
wait_for_completion: bool = True,
|
|
131
|
-
name: str | None = None,
|
|
132
|
-
) -> str:
|
|
133
|
-
"""Connect two nodes to enable message flow between them.
|
|
134
|
-
|
|
135
|
-
Nodes can be agents or teams.
|
|
136
|
-
|
|
137
|
-
Args:
|
|
138
|
-
source: Name of the source node
|
|
139
|
-
target: Name of the target node
|
|
140
|
-
connection_type: How messages should be handled:
|
|
141
|
-
- run: Execute message as a new run in target
|
|
142
|
-
- context: Add message as context to target
|
|
143
|
-
- forward: Forward message to target's outbox
|
|
144
|
-
priority: Task priority (lower = higher priority)
|
|
145
|
-
delay_seconds: Optional delay before processing messages
|
|
146
|
-
queued: Whether messages should be queued for manual processing
|
|
147
|
-
queue_strategy: How to process queued messages:
|
|
148
|
-
- concat: Combine all messages with newlines
|
|
149
|
-
- latest: Use only the most recent message
|
|
150
|
-
- buffer: Process all messages individually
|
|
151
|
-
wait_for_completion: Whether to wait for target to complete
|
|
152
|
-
name: Optional name for this connection
|
|
153
|
-
|
|
154
|
-
Returns:
|
|
155
|
-
Description of the created connection
|
|
156
|
-
"""
|
|
157
|
-
if not ctx.pool:
|
|
158
|
-
msg = "No agent pool available"
|
|
159
|
-
raise ToolError(msg)
|
|
160
|
-
|
|
161
|
-
# Get the nodes
|
|
162
|
-
if source not in ctx.pool.nodes:
|
|
163
|
-
msg = (
|
|
164
|
-
f"No agent or team found with name: {source}. "
|
|
165
|
-
f"Available nodes: {', '.join(ctx.pool.nodes.keys())}"
|
|
166
|
-
)
|
|
167
|
-
raise ModelRetry(msg)
|
|
168
|
-
if target not in ctx.pool.nodes:
|
|
169
|
-
msg = (
|
|
170
|
-
f"No agent or team found with name: {target}. "
|
|
171
|
-
f"Available nodes: {', '.join(ctx.pool.nodes.keys())}"
|
|
172
|
-
)
|
|
173
|
-
raise ModelRetry(msg)
|
|
174
|
-
|
|
175
|
-
source_node = ctx.pool.nodes[source]
|
|
176
|
-
target_node = ctx.pool.nodes[target]
|
|
177
|
-
|
|
178
|
-
# Create the connection
|
|
179
|
-
delay = timedelta(seconds=delay_seconds) if delay_seconds is not None else None
|
|
180
|
-
_talk = source_node.connect_to(
|
|
181
|
-
target_node,
|
|
182
|
-
connection_type=connection_type,
|
|
183
|
-
priority=priority,
|
|
184
|
-
delay=delay,
|
|
185
|
-
queued=queued,
|
|
186
|
-
queue_strategy=queue_strategy,
|
|
187
|
-
name=name,
|
|
188
|
-
)
|
|
189
|
-
source_node.connections.set_wait_state(target_node, wait=wait_for_completion)
|
|
190
|
-
|
|
191
|
-
return (
|
|
192
|
-
f"Created connection from **{source}** to **{target}** "
|
|
193
|
-
f"*(type={connection_type}, queued={queued}, "
|
|
194
|
-
f"strategy={queue_strategy if queued else 'n/a'})*"
|
|
195
|
-
)
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
class AgentManagementTools(StaticResourceProvider):
|
|
199
|
-
"""Provider for agent pool building tools."""
|
|
200
|
-
|
|
201
|
-
def __init__(self, name: str = "agent_management") -> None:
|
|
202
|
-
super().__init__(name=name)
|
|
203
|
-
for tool in [
|
|
204
|
-
self.create_tool(create_worker_agent, category="other", destructive=False),
|
|
205
|
-
self.create_tool(add_agent, category="other", destructive=False),
|
|
206
|
-
self.create_tool(add_team, category="other", destructive=False),
|
|
207
|
-
self.create_tool(connect_nodes, category="other", destructive=False),
|
|
208
|
-
]:
|
|
209
|
-
self.add_tool(tool)
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
if __name__ == "__main__":
|
|
213
|
-
# import logging
|
|
214
|
-
from agentpool import AgentPool
|
|
215
|
-
|
|
216
|
-
user_prompt = """Add a stdio MCP server:
|
|
217
|
-
// "command": "npx",
|
|
218
|
-
// "args": ["mcp-graphql"],
|
|
219
|
-
// "env": { "ENDPOINT": "https://diego.one/graphql" }
|
|
220
|
-
|
|
221
|
-
."""
|
|
222
|
-
|
|
223
|
-
async def main() -> None:
|
|
224
|
-
from agentpool_config.toolsets import IntegrationToolsetConfig
|
|
225
|
-
|
|
226
|
-
async with AgentPool() as pool:
|
|
227
|
-
toolsets = [IntegrationToolsetConfig()]
|
|
228
|
-
toolset_providers = [config.get_provider() for config in toolsets]
|
|
229
|
-
agent = await pool.add_agent(
|
|
230
|
-
"X",
|
|
231
|
-
toolsets=toolset_providers,
|
|
232
|
-
model="openai:gpt-5-nano",
|
|
233
|
-
)
|
|
234
|
-
result = await agent.run(user_prompt)
|
|
235
|
-
print(result)
|
|
236
|
-
result = await agent.run("Which tools does it have?")
|
|
237
|
-
print(result)
|
|
238
|
-
|
|
239
|
-
anyio.run(main)
|
|
@@ -1,288 +0,0 @@
|
|
|
1
|
-
"""Tool to chain multiple function calls."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import asyncio
|
|
6
|
-
from dataclasses import dataclass
|
|
7
|
-
from enum import StrEnum
|
|
8
|
-
from typing import Any, Literal, assert_never
|
|
9
|
-
|
|
10
|
-
import anyio
|
|
11
|
-
from pydantic import Field
|
|
12
|
-
from pydantic_ai import ModelRetry
|
|
13
|
-
from schemez import Schema
|
|
14
|
-
|
|
15
|
-
from agentpool.agents.context import AgentContext # noqa: TC001
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class ErrorStrategy(StrEnum):
|
|
19
|
-
"""Strategy for handling errors in the pipeline."""
|
|
20
|
-
|
|
21
|
-
STOP = "stop" # Stop pipeline on error
|
|
22
|
-
SKIP = "skip" # Skip failed step, continue with previous result
|
|
23
|
-
DEFAULT = "default" # Use provided default value
|
|
24
|
-
RETRY = "retry" # Retry the step
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class StepCondition(Schema):
|
|
28
|
-
"""Condition for conditional execution."""
|
|
29
|
-
|
|
30
|
-
field: str # Field to check in result
|
|
31
|
-
operator: Literal["eq", "gt", "lt", "contains", "exists"]
|
|
32
|
-
value: Any = None
|
|
33
|
-
|
|
34
|
-
def evaluate_with_value(self, value: Any) -> bool:
|
|
35
|
-
"""Evaluate this condition against a value.
|
|
36
|
-
|
|
37
|
-
Args:
|
|
38
|
-
value: The value to evaluate against the condition.
|
|
39
|
-
|
|
40
|
-
Returns:
|
|
41
|
-
bool: True if the condition is met, False otherwise.
|
|
42
|
-
"""
|
|
43
|
-
field_value = value.get(self.field) if isinstance(value, dict) else value
|
|
44
|
-
|
|
45
|
-
match self.operator:
|
|
46
|
-
case "eq":
|
|
47
|
-
return bool(field_value == self.value)
|
|
48
|
-
case "gt":
|
|
49
|
-
return bool(field_value > self.value)
|
|
50
|
-
case "lt":
|
|
51
|
-
return bool(field_value < self.value)
|
|
52
|
-
case "contains":
|
|
53
|
-
try:
|
|
54
|
-
return self.value in field_value # type: ignore[operator]
|
|
55
|
-
except TypeError:
|
|
56
|
-
return False
|
|
57
|
-
case "exists":
|
|
58
|
-
return field_value is not None
|
|
59
|
-
case _ as unreachable:
|
|
60
|
-
assert_never(unreachable)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
@dataclass
|
|
64
|
-
class StepResult:
|
|
65
|
-
"""Result of a pipeline step execution."""
|
|
66
|
-
|
|
67
|
-
success: bool
|
|
68
|
-
result: Any
|
|
69
|
-
error: Exception | None = None
|
|
70
|
-
retries: int = 0
|
|
71
|
-
duration: float = 0.0
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
# Type alias for step results during execution
|
|
75
|
-
type StepResults = dict[str, StepResult]
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
class PipelineStep(Schema):
|
|
79
|
-
"""Single step in a tool pipeline."""
|
|
80
|
-
|
|
81
|
-
tool: str
|
|
82
|
-
input_kwarg: str = "text"
|
|
83
|
-
keyword_args: dict[str, Any] = Field(default_factory=dict)
|
|
84
|
-
name: str | None = None # Optional step name for referencing
|
|
85
|
-
condition: StepCondition | None = None # Conditional execution
|
|
86
|
-
error_strategy: ErrorStrategy = ErrorStrategy.STOP
|
|
87
|
-
default_value: Any = None # Used with ErrorStrategy.DEFAULT
|
|
88
|
-
max_retries: int = 0
|
|
89
|
-
retry_delay: float = 1.0
|
|
90
|
-
timeout: float | None = None
|
|
91
|
-
depends_on: list[str] = Field(default_factory=list) # Step dependencies
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
class Pipeline(Schema):
|
|
95
|
-
"""A pipeline of tool operations."""
|
|
96
|
-
|
|
97
|
-
input: str | dict[str, Any]
|
|
98
|
-
steps: list[PipelineStep]
|
|
99
|
-
mode: Literal["sequential", "parallel"] = "sequential"
|
|
100
|
-
max_parallel: int = 5 # Max concurrent steps
|
|
101
|
-
collect_metrics: bool = False # Collect execution metrics
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
async def _execute_step(
|
|
105
|
-
ctx: AgentContext,
|
|
106
|
-
step: PipelineStep,
|
|
107
|
-
input_value: Any,
|
|
108
|
-
results: StepResults,
|
|
109
|
-
) -> StepResult:
|
|
110
|
-
"""Execute a single pipeline step."""
|
|
111
|
-
start_time = asyncio.get_event_loop().time()
|
|
112
|
-
retries = 0
|
|
113
|
-
|
|
114
|
-
while True:
|
|
115
|
-
try:
|
|
116
|
-
# Check condition if any
|
|
117
|
-
if step.condition and not step.condition.evaluate_with_value(input_value):
|
|
118
|
-
return StepResult(success=True, result=input_value, duration=0)
|
|
119
|
-
|
|
120
|
-
tool_info = await ctx.agent.tools.get_tool(step.tool) # Get the tool
|
|
121
|
-
if isinstance(input_value, dict): # Prepare kwargs
|
|
122
|
-
kwargs = {**input_value, **step.keyword_args}
|
|
123
|
-
else:
|
|
124
|
-
kwargs = {step.input_kwarg: input_value, **step.keyword_args}
|
|
125
|
-
|
|
126
|
-
# Execute with timeout if specified
|
|
127
|
-
if step.timeout:
|
|
128
|
-
fut = tool_info.execute(ctx, **kwargs)
|
|
129
|
-
result = await asyncio.wait_for(fut, timeout=step.timeout)
|
|
130
|
-
else:
|
|
131
|
-
result = await tool_info.execute(ctx, **kwargs)
|
|
132
|
-
|
|
133
|
-
duration = asyncio.get_event_loop().time() - start_time
|
|
134
|
-
return StepResult(success=True, result=result, duration=duration)
|
|
135
|
-
|
|
136
|
-
except Exception as exc:
|
|
137
|
-
match step.error_strategy:
|
|
138
|
-
case ErrorStrategy.STOP:
|
|
139
|
-
raise
|
|
140
|
-
|
|
141
|
-
case ErrorStrategy.SKIP:
|
|
142
|
-
duration = asyncio.get_event_loop().time() - start_time
|
|
143
|
-
return StepResult(
|
|
144
|
-
success=False,
|
|
145
|
-
result=input_value,
|
|
146
|
-
error=exc,
|
|
147
|
-
duration=duration,
|
|
148
|
-
)
|
|
149
|
-
|
|
150
|
-
case ErrorStrategy.DEFAULT:
|
|
151
|
-
duration = asyncio.get_event_loop().time() - start_time
|
|
152
|
-
return StepResult(
|
|
153
|
-
success=False,
|
|
154
|
-
result=step.default_value,
|
|
155
|
-
error=exc,
|
|
156
|
-
duration=duration,
|
|
157
|
-
)
|
|
158
|
-
|
|
159
|
-
case ErrorStrategy.RETRY:
|
|
160
|
-
retries += 1
|
|
161
|
-
if retries <= step.max_retries:
|
|
162
|
-
await anyio.sleep(step.retry_delay)
|
|
163
|
-
continue
|
|
164
|
-
raise # Max retries exceeded
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
async def _execute_sequential(ctx: AgentContext, pipeline: Pipeline, results: StepResults) -> Any:
|
|
168
|
-
"""Execute steps sequentially."""
|
|
169
|
-
current = pipeline.input
|
|
170
|
-
for step in pipeline.steps:
|
|
171
|
-
result = await _execute_step(ctx, step, current, results)
|
|
172
|
-
if step.name:
|
|
173
|
-
results[step.name] = result
|
|
174
|
-
current = result.result
|
|
175
|
-
return current
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
async def _execute_parallel(ctx: AgentContext, pipeline: Pipeline, results: StepResults) -> Any:
|
|
179
|
-
"""Execute independent steps in parallel."""
|
|
180
|
-
semaphore = asyncio.Semaphore(pipeline.max_parallel)
|
|
181
|
-
|
|
182
|
-
async def run_step(step: PipelineStep) -> None:
|
|
183
|
-
async with semaphore:
|
|
184
|
-
# Wait for dependencies
|
|
185
|
-
for dep in step.depends_on:
|
|
186
|
-
while dep not in results:
|
|
187
|
-
await anyio.sleep(0.1)
|
|
188
|
-
|
|
189
|
-
# Get input from dependency or pipeline input
|
|
190
|
-
input_value = results[step.depends_on[-1]].result if step.depends_on else pipeline.input
|
|
191
|
-
result = await _execute_step(ctx, step, input_value, results)
|
|
192
|
-
if step.name:
|
|
193
|
-
results[step.name] = result
|
|
194
|
-
|
|
195
|
-
# Create tasks for all steps
|
|
196
|
-
tasks = [run_step(step) for step in pipeline.steps]
|
|
197
|
-
await asyncio.gather(*tasks)
|
|
198
|
-
# Return last result
|
|
199
|
-
return results[name].result if (name := pipeline.steps[-1].name) else None
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
async def chain_tools(
|
|
203
|
-
ctx: AgentContext,
|
|
204
|
-
input_data: str | dict[str, Any],
|
|
205
|
-
steps: list[dict[str, Any]],
|
|
206
|
-
mode: Literal["sequential", "parallel"] = "sequential",
|
|
207
|
-
max_parallel: int = 5,
|
|
208
|
-
collect_metrics: bool = False,
|
|
209
|
-
) -> Any:
|
|
210
|
-
"""Execute multiple tool operations in sequence or parallel.
|
|
211
|
-
|
|
212
|
-
WHEN TO USE THIS TOOL:
|
|
213
|
-
- Use this when you can plan multiple operations confidently in advance
|
|
214
|
-
- Use this for common sequences you've successfully used before
|
|
215
|
-
- Use this to reduce interaction rounds for known operation patterns
|
|
216
|
-
- Use this when all steps are independent of intermediate results
|
|
217
|
-
|
|
218
|
-
DO NOT USE THIS TOOL:
|
|
219
|
-
- When you need to inspect intermediate results
|
|
220
|
-
- When next steps depend on analyzing previous results
|
|
221
|
-
- When you're unsure about the complete sequence
|
|
222
|
-
- When you need to handle errors at each step individually
|
|
223
|
-
|
|
224
|
-
Args:
|
|
225
|
-
ctx: Agent context for tool execution
|
|
226
|
-
input_data: Initial input for the pipeline
|
|
227
|
-
steps: List of step configurations, each containing:
|
|
228
|
-
- tool: Name of the tool to execute
|
|
229
|
-
- input_kwarg: Keyword argument name for input (default: "text")
|
|
230
|
-
- keyword_args: Additional keyword arguments
|
|
231
|
-
- name: Optional step name for referencing
|
|
232
|
-
- condition: Optional execution condition
|
|
233
|
-
- error_strategy: How to handle errors ("stop", "skip", "default", "retry")
|
|
234
|
-
- default_value: Value to use with "default" error strategy
|
|
235
|
-
- max_retries: Maximum retry attempts
|
|
236
|
-
- retry_delay: Delay between retries in seconds
|
|
237
|
-
- timeout: Step timeout in seconds
|
|
238
|
-
- depends_on: List of step names this depends on
|
|
239
|
-
mode: Execution mode - "sequential" or "parallel"
|
|
240
|
-
max_parallel: Maximum concurrent steps for parallel mode
|
|
241
|
-
collect_metrics: Whether to collect execution metrics
|
|
242
|
-
|
|
243
|
-
Examples:
|
|
244
|
-
# Sequential processing
|
|
245
|
-
await chain_tools(
|
|
246
|
-
ctx,
|
|
247
|
-
input_data="main.py",
|
|
248
|
-
steps=[
|
|
249
|
-
{"tool": "load_resource", "input_kwarg": "name"},
|
|
250
|
-
{"tool": "analyze_code", "input_kwarg": "code"},
|
|
251
|
-
{"tool": "format_output", "input_kwarg": "text"}
|
|
252
|
-
]
|
|
253
|
-
)
|
|
254
|
-
|
|
255
|
-
# Parallel processing with dependencies
|
|
256
|
-
await chain_tools(
|
|
257
|
-
ctx,
|
|
258
|
-
input_data="test.py",
|
|
259
|
-
mode="parallel",
|
|
260
|
-
steps=[
|
|
261
|
-
{"tool": "load_resource", "input_kwarg": "name", "name": "load"},
|
|
262
|
-
{"tool": "analyze_code", "input_kwarg": "code", "depends_on": ["load"]},
|
|
263
|
-
{"tool": "count_tokens", "input_kwarg": "text", "depends_on": ["load"]}
|
|
264
|
-
]
|
|
265
|
-
)
|
|
266
|
-
"""
|
|
267
|
-
try:
|
|
268
|
-
pipeline = Pipeline(
|
|
269
|
-
input=input_data,
|
|
270
|
-
steps=[PipelineStep.model_validate(step) for step in steps],
|
|
271
|
-
mode=mode,
|
|
272
|
-
max_parallel=max_parallel,
|
|
273
|
-
collect_metrics=collect_metrics,
|
|
274
|
-
)
|
|
275
|
-
except Exception as e:
|
|
276
|
-
msg = f"Invalid pipeline configuration: {e}"
|
|
277
|
-
raise ModelRetry(msg) from e
|
|
278
|
-
results: StepResults = {}
|
|
279
|
-
|
|
280
|
-
try:
|
|
281
|
-
match pipeline.mode:
|
|
282
|
-
case "sequential":
|
|
283
|
-
return await _execute_sequential(ctx, pipeline, results)
|
|
284
|
-
case "parallel":
|
|
285
|
-
return await _execute_parallel(ctx, pipeline, results)
|
|
286
|
-
except Exception as e:
|
|
287
|
-
msg = f"Failed to execute pipeline: {e}"
|
|
288
|
-
raise ModelRetry(msg) from e
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
"""Provider for history tools."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
from agentpool.agents.context import AgentContext # noqa: TC001
|
|
6
|
-
from agentpool.resource_providers import StaticResourceProvider
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
async def search_history(
|
|
10
|
-
ctx: AgentContext,
|
|
11
|
-
query: str | None = None,
|
|
12
|
-
hours: int = 24,
|
|
13
|
-
limit: int = 5,
|
|
14
|
-
) -> str:
|
|
15
|
-
"""Search conversation history."""
|
|
16
|
-
from agentpool_storage.formatters import format_output
|
|
17
|
-
|
|
18
|
-
if not ctx.pool:
|
|
19
|
-
return "No agent pool available for history search"
|
|
20
|
-
provider = ctx.pool.storage.get_history_provider()
|
|
21
|
-
results = await provider.get_filtered_conversations(
|
|
22
|
-
query=query,
|
|
23
|
-
period=f"{hours}h",
|
|
24
|
-
limit=limit,
|
|
25
|
-
)
|
|
26
|
-
return format_output(results)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
class HistoryTools(StaticResourceProvider):
|
|
30
|
-
"""Provider for history tools."""
|
|
31
|
-
|
|
32
|
-
def __init__(self, name: str = "history") -> None:
|
|
33
|
-
super().__init__(name=name)
|
|
34
|
-
self._tools = [
|
|
35
|
-
self.create_tool(search_history, category="search", read_only=True, idempotent=True),
|
|
36
|
-
]
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
"""Provider for integration tools."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
from typing import TYPE_CHECKING, Literal
|
|
6
|
-
|
|
7
|
-
from pydantic import HttpUrl
|
|
8
|
-
|
|
9
|
-
from agentpool.agents.context import AgentContext # noqa: TC001
|
|
10
|
-
from agentpool.resource_providers import ResourceProvider
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
if TYPE_CHECKING:
|
|
14
|
-
from agentpool.tools.base import Tool
|
|
15
|
-
from agentpool_config.mcp_server import MCPServerConfig
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
async def add_local_mcp_server( # noqa: D417
|
|
19
|
-
ctx: AgentContext,
|
|
20
|
-
name: str,
|
|
21
|
-
command: str,
|
|
22
|
-
args: list[str] | None = None,
|
|
23
|
-
env_vars: dict[str, str] | None = None,
|
|
24
|
-
) -> str:
|
|
25
|
-
"""Add a local MCP server via stdio transport.
|
|
26
|
-
|
|
27
|
-
Args:
|
|
28
|
-
name: Unique name for the MCP server
|
|
29
|
-
command: Command to execute for the server
|
|
30
|
-
args: Command arguments
|
|
31
|
-
env_vars: Environment variables to pass to the server
|
|
32
|
-
|
|
33
|
-
Returns:
|
|
34
|
-
Confirmation message about the added server
|
|
35
|
-
"""
|
|
36
|
-
from agentpool_config.mcp_server import StdioMCPServerConfig
|
|
37
|
-
|
|
38
|
-
env = env_vars or {}
|
|
39
|
-
config = StdioMCPServerConfig(name=name, command=command, args=args or [], env=env)
|
|
40
|
-
await ctx.agent.mcp.setup_server_runtime(config)
|
|
41
|
-
# New provider automatically available via aggregating provider
|
|
42
|
-
return f"Added local MCP server **{name}** with command: **{command}**"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
async def add_remote_mcp_server( # noqa: D417
|
|
46
|
-
ctx: AgentContext,
|
|
47
|
-
name: str,
|
|
48
|
-
url: str,
|
|
49
|
-
transport: Literal["sse", "streamable-http"] = "streamable-http",
|
|
50
|
-
) -> str:
|
|
51
|
-
"""Add a remote MCP server via HTTP-based transport.
|
|
52
|
-
|
|
53
|
-
Args:
|
|
54
|
-
name: Unique name for the MCP server
|
|
55
|
-
url: Server URL endpoint
|
|
56
|
-
transport: HTTP transport type to use (http is preferred)
|
|
57
|
-
|
|
58
|
-
Returns:
|
|
59
|
-
Confirmation message about the added server
|
|
60
|
-
"""
|
|
61
|
-
from agentpool_config.mcp_server import SSEMCPServerConfig, StreamableHTTPMCPServerConfig
|
|
62
|
-
|
|
63
|
-
match transport:
|
|
64
|
-
case "sse":
|
|
65
|
-
config: MCPServerConfig = SSEMCPServerConfig(name=name, url=HttpUrl(url))
|
|
66
|
-
case "streamable-http":
|
|
67
|
-
config = StreamableHTTPMCPServerConfig(name=name, url=HttpUrl(url))
|
|
68
|
-
|
|
69
|
-
await ctx.agent.mcp.setup_server_runtime(config)
|
|
70
|
-
# New provider automatically available via aggregating provider
|
|
71
|
-
return f"Added remote MCP server **{name}** at *{url}* using {transport} transport"
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
class IntegrationTools(ResourceProvider):
|
|
75
|
-
"""Provider for integration tools."""
|
|
76
|
-
|
|
77
|
-
def __init__(self, name: str = "integrations") -> None:
|
|
78
|
-
super().__init__(name)
|
|
79
|
-
|
|
80
|
-
async def get_tools(self) -> list[Tool]:
|
|
81
|
-
"""Get integration tools."""
|
|
82
|
-
return [
|
|
83
|
-
self.create_tool(add_local_mcp_server, category="other"),
|
|
84
|
-
self.create_tool(add_remote_mcp_server, category="other", open_world=True),
|
|
85
|
-
]
|