Coverage for mcpgateway / plugins / framework / hooks / agents.py: 97%
30 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-02-11 07:10 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-02-11 07:10 +0000
1# -*- coding: utf-8 -*-
2"""Location: ./mcpgateway/plugins/models/agents.py
3Copyright 2025
4SPDX-License-Identifier: Apache-2.0
5Authors: Teryl Taylor
7Pydantic models for agent plugins.
8This module implements the pydantic models associated with
9the base plugin layer including configurations, and contexts.
10"""
12# Standard
13from enum import Enum
14from typing import Any, Dict, List, Optional
16# Third-Party
17from pydantic import Field
19# First-Party
20from mcpgateway.common.models import Message
21from mcpgateway.plugins.framework.hooks.http import HttpHeaderPayload
22from mcpgateway.plugins.framework.models import PluginPayload, PluginResult
25class AgentHookType(str, Enum):
26 """Agent hook points.
28 Attributes:
29 AGENT_PRE_INVOKE: Before agent invocation.
30 AGENT_POST_INVOKE: After agent responds.
32 Examples:
33 >>> AgentHookType.AGENT_PRE_INVOKE
34 <AgentHookType.AGENT_PRE_INVOKE: 'agent_pre_invoke'>
35 >>> AgentHookType.AGENT_PRE_INVOKE.value
36 'agent_pre_invoke'
37 >>> AgentHookType('agent_post_invoke')
38 <AgentHookType.AGENT_POST_INVOKE: 'agent_post_invoke'>
39 >>> list(AgentHookType)
40 [<AgentHookType.AGENT_PRE_INVOKE: 'agent_pre_invoke'>, <AgentHookType.AGENT_POST_INVOKE: 'agent_post_invoke'>]
41 """
43 AGENT_PRE_INVOKE = "agent_pre_invoke"
44 AGENT_POST_INVOKE = "agent_post_invoke"
47class AgentPreInvokePayload(PluginPayload):
48 """Agent payload for pre-invoke hook.
50 Attributes:
51 agent_id: The agent identifier (can be modified for routing).
52 messages: Conversation messages (can be filtered/transformed).
53 tools: Optional list of tools available to agent.
54 headers: Optional HTTP headers.
55 model: Optional model override.
56 system_prompt: Optional system instructions.
57 parameters: Optional LLM parameters (temperature, max_tokens, etc.).
59 Examples:
60 >>> payload = AgentPreInvokePayload(agent_id="agent-123", messages=[])
61 >>> payload.agent_id
62 'agent-123'
63 >>> payload.messages
64 []
65 >>> payload.tools is None
66 True
67 >>> from mcpgateway.common.models import Message, Role, TextContent
68 >>> msg = Message(role=Role.USER, content=TextContent(type="text", text="Hello"))
69 >>> payload = AgentPreInvokePayload(
70 ... agent_id="agent-456",
71 ... messages=[msg],
72 ... tools=["search", "calculator"],
73 ... model="claude-3-5-sonnet-20241022"
74 ... )
75 >>> payload.tools
76 ['search', 'calculator']
77 >>> payload.model
78 'claude-3-5-sonnet-20241022'
79 """
81 agent_id: str
82 messages: List[Message]
83 tools: Optional[List[str]] = None
84 headers: Optional[HttpHeaderPayload] = None
85 model: Optional[str] = None
86 system_prompt: Optional[str] = None
87 parameters: Optional[Dict[str, Any]] = Field(default_factory=dict)
90class AgentPostInvokePayload(PluginPayload):
91 """Agent payload for post-invoke hook.
93 Attributes:
94 agent_id: The agent identifier.
95 messages: Response messages from agent (can be filtered/transformed).
96 tool_calls: Optional tool invocations made by agent.
98 Examples:
99 >>> payload = AgentPostInvokePayload(agent_id="agent-123", messages=[])
100 >>> payload.agent_id
101 'agent-123'
102 >>> payload.messages
103 []
104 >>> payload.tool_calls is None
105 True
106 >>> from mcpgateway.common.models import Message, Role, TextContent
107 >>> msg = Message(role=Role.ASSISTANT, content=TextContent(type="text", text="Response"))
108 >>> payload = AgentPostInvokePayload(
109 ... agent_id="agent-456",
110 ... messages=[msg],
111 ... tool_calls=[{"name": "search", "arguments": {"query": "test"}}]
112 ... )
113 >>> payload.tool_calls
114 [{'name': 'search', 'arguments': {'query': 'test'}}]
115 """
117 agent_id: str
118 messages: List[Message]
119 tool_calls: Optional[List[Dict[str, Any]]] = None
122AgentPreInvokeResult = PluginResult[AgentPreInvokePayload]
123AgentPostInvokeResult = PluginResult[AgentPostInvokePayload]
126def _register_agent_hooks() -> None:
127 """Register agent hooks in the global registry.
129 This is called lazily to avoid circular import issues.
130 """
131 # Import here to avoid circular dependency at module load time
132 # First-Party
133 from mcpgateway.plugins.framework.hooks.registry import get_hook_registry # pylint: disable=import-outside-toplevel
135 registry = get_hook_registry()
137 # Only register if not already registered (idempotent)
138 if not registry.is_registered(AgentHookType.AGENT_PRE_INVOKE): 138 ↛ exitline 138 didn't return from function '_register_agent_hooks' because the condition on line 138 was always true
139 registry.register_hook(AgentHookType.AGENT_PRE_INVOKE, AgentPreInvokePayload, AgentPreInvokeResult)
140 registry.register_hook(AgentHookType.AGENT_POST_INVOKE, AgentPostInvokePayload, AgentPostInvokeResult)
143_register_agent_hooks()