agent_os_kernel 3.1.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.
- agent_control_plane/__init__.py +662 -0
- agent_control_plane/a2a_adapter.py +543 -0
- agent_control_plane/adapter.py +417 -0
- agent_control_plane/agent_hibernation.py +394 -0
- agent_control_plane/agent_kernel.py +470 -0
- agent_control_plane/compliance.py +720 -0
- agent_control_plane/constraint_graphs.py +478 -0
- agent_control_plane/control_plane.py +854 -0
- agent_control_plane/example_executors.py +195 -0
- agent_control_plane/execution_engine.py +231 -0
- agent_control_plane/flight_recorder.py +846 -0
- agent_control_plane/governance_layer.py +435 -0
- agent_control_plane/hf_utils.py +563 -0
- agent_control_plane/interfaces/__init__.py +55 -0
- agent_control_plane/interfaces/kernel_interface.py +361 -0
- agent_control_plane/interfaces/plugin_interface.py +497 -0
- agent_control_plane/interfaces/protocol_interfaces.py +387 -0
- agent_control_plane/kernel_space.py +1009 -0
- agent_control_plane/langchain_adapter.py +424 -0
- agent_control_plane/lifecycle.py +3113 -0
- agent_control_plane/mcp_adapter.py +653 -0
- agent_control_plane/ml_safety.py +563 -0
- agent_control_plane/multimodal.py +727 -0
- agent_control_plane/mute_agent.py +422 -0
- agent_control_plane/observability.py +787 -0
- agent_control_plane/orchestrator.py +482 -0
- agent_control_plane/plugin_registry.py +750 -0
- agent_control_plane/policy_engine.py +954 -0
- agent_control_plane/process_isolation.py +777 -0
- agent_control_plane/shadow_mode.py +310 -0
- agent_control_plane/signals.py +493 -0
- agent_control_plane/supervisor_agents.py +430 -0
- agent_control_plane/time_travel_debugger.py +557 -0
- agent_control_plane/tool_registry.py +452 -0
- agent_control_plane/vfs.py +697 -0
- agent_kernel/__init__.py +69 -0
- agent_kernel/analyzer.py +435 -0
- agent_kernel/auditor.py +36 -0
- agent_kernel/completeness_auditor.py +237 -0
- agent_kernel/detector.py +203 -0
- agent_kernel/kernel.py +744 -0
- agent_kernel/memory_manager.py +85 -0
- agent_kernel/models.py +374 -0
- agent_kernel/nudge_mechanism.py +263 -0
- agent_kernel/outcome_analyzer.py +338 -0
- agent_kernel/patcher.py +582 -0
- agent_kernel/semantic_analyzer.py +316 -0
- agent_kernel/semantic_purge.py +349 -0
- agent_kernel/simulator.py +449 -0
- agent_kernel/teacher.py +85 -0
- agent_kernel/triage.py +152 -0
- agent_os/__init__.py +409 -0
- agent_os/_adversarial_impl.py +200 -0
- agent_os/_circuit_breaker_impl.py +232 -0
- agent_os/_mcp_metrics.py +193 -0
- agent_os/adversarial.py +20 -0
- agent_os/agents_compat.py +490 -0
- agent_os/audit_logger.py +135 -0
- agent_os/base_agent.py +651 -0
- agent_os/circuit_breaker.py +34 -0
- agent_os/cli/__init__.py +659 -0
- agent_os/cli/cmd_audit.py +128 -0
- agent_os/cli/cmd_init.py +152 -0
- agent_os/cli/cmd_policy.py +41 -0
- agent_os/cli/cmd_policy_gen.py +180 -0
- agent_os/cli/cmd_validate.py +258 -0
- agent_os/cli/mcp_scan.py +265 -0
- agent_os/cli/output.py +192 -0
- agent_os/cli/policy_checker.py +330 -0
- agent_os/compat.py +74 -0
- agent_os/constraint_graph.py +234 -0
- agent_os/content_governance.py +140 -0
- agent_os/context_budget.py +305 -0
- agent_os/credential_redactor.py +224 -0
- agent_os/diff_policy.py +89 -0
- agent_os/egress_policy.py +159 -0
- agent_os/escalation.py +276 -0
- agent_os/event_bus.py +124 -0
- agent_os/exceptions.py +180 -0
- agent_os/execution_context_policy.py +141 -0
- agent_os/github_enterprise.py +96 -0
- agent_os/health.py +20 -0
- agent_os/integrations/__init__.py +279 -0
- agent_os/integrations/a2a_adapter.py +279 -0
- agent_os/integrations/agent_lightning/__init__.py +30 -0
- agent_os/integrations/anthropic_adapter.py +420 -0
- agent_os/integrations/autogen_adapter.py +620 -0
- agent_os/integrations/base.py +1137 -0
- agent_os/integrations/compat.py +229 -0
- agent_os/integrations/config.py +98 -0
- agent_os/integrations/conversation_guardian.py +957 -0
- agent_os/integrations/crewai_adapter.py +467 -0
- agent_os/integrations/drift_detector.py +425 -0
- agent_os/integrations/dry_run.py +124 -0
- agent_os/integrations/escalation.py +582 -0
- agent_os/integrations/gemini_adapter.py +364 -0
- agent_os/integrations/google_adk_adapter.py +633 -0
- agent_os/integrations/guardrails_adapter.py +394 -0
- agent_os/integrations/health.py +197 -0
- agent_os/integrations/langchain_adapter.py +654 -0
- agent_os/integrations/llamafirewall.py +343 -0
- agent_os/integrations/llamaindex_adapter.py +188 -0
- agent_os/integrations/logging.py +191 -0
- agent_os/integrations/maf_adapter.py +631 -0
- agent_os/integrations/mistral_adapter.py +365 -0
- agent_os/integrations/openai_adapter.py +816 -0
- agent_os/integrations/openai_agents_sdk.py +406 -0
- agent_os/integrations/policy_compose.py +171 -0
- agent_os/integrations/profiling.py +144 -0
- agent_os/integrations/pydantic_ai_adapter.py +420 -0
- agent_os/integrations/rate_limiter.py +130 -0
- agent_os/integrations/rbac.py +143 -0
- agent_os/integrations/registry.py +113 -0
- agent_os/integrations/scope_guard.py +303 -0
- agent_os/integrations/semantic_kernel_adapter.py +769 -0
- agent_os/integrations/smolagents_adapter.py +629 -0
- agent_os/integrations/templates.py +178 -0
- agent_os/integrations/token_budget.py +134 -0
- agent_os/integrations/tool_aliases.py +190 -0
- agent_os/integrations/webhooks.py +177 -0
- agent_os/lite.py +208 -0
- agent_os/mcp_gateway.py +385 -0
- agent_os/mcp_message_signer.py +273 -0
- agent_os/mcp_protocols.py +161 -0
- agent_os/mcp_response_scanner.py +232 -0
- agent_os/mcp_security.py +924 -0
- agent_os/mcp_session_auth.py +231 -0
- agent_os/mcp_sliding_rate_limiter.py +184 -0
- agent_os/memory_guard.py +409 -0
- agent_os/metrics.py +134 -0
- agent_os/mute.py +428 -0
- agent_os/mute_agent.py +209 -0
- agent_os/policies/__init__.py +77 -0
- agent_os/policies/async_evaluator.py +275 -0
- agent_os/policies/backends.py +670 -0
- agent_os/policies/bridge.py +169 -0
- agent_os/policies/budget.py +85 -0
- agent_os/policies/cli.py +294 -0
- agent_os/policies/conflict_resolution.py +270 -0
- agent_os/policies/data_classification.py +252 -0
- agent_os/policies/evaluator.py +239 -0
- agent_os/policies/policy_schema.json +228 -0
- agent_os/policies/rate_limiting.py +145 -0
- agent_os/policies/schema.py +115 -0
- agent_os/policies/shared.py +331 -0
- agent_os/prompt_injection.py +694 -0
- agent_os/providers.py +182 -0
- agent_os/py.typed +0 -0
- agent_os/retry.py +81 -0
- agent_os/reversibility.py +251 -0
- agent_os/sandbox.py +432 -0
- agent_os/sandbox_provider.py +140 -0
- agent_os/secure_codegen.py +525 -0
- agent_os/security_skills.py +538 -0
- agent_os/semantic_policy.py +422 -0
- agent_os/server/__init__.py +15 -0
- agent_os/server/__main__.py +25 -0
- agent_os/server/app.py +277 -0
- agent_os/server/models.py +104 -0
- agent_os/shift_left_metrics.py +130 -0
- agent_os/stateless.py +742 -0
- agent_os/supervisor.py +148 -0
- agent_os/task_outcome.py +148 -0
- agent_os/transparency.py +181 -0
- agent_os/trust_root.py +128 -0
- agent_os_kernel-3.1.0.dist-info/METADATA +1269 -0
- agent_os_kernel-3.1.0.dist-info/RECORD +337 -0
- agent_os_kernel-3.1.0.dist-info/WHEEL +4 -0
- agent_os_kernel-3.1.0.dist-info/entry_points.txt +2 -0
- agent_os_kernel-3.1.0.dist-info/licenses/LICENSE +21 -0
- agent_os_observability/__init__.py +27 -0
- agent_os_observability/dashboards.py +898 -0
- agent_os_observability/metrics.py +398 -0
- agent_os_observability/server.py +223 -0
- agent_os_observability/tracer.py +232 -0
- agent_primitives/__init__.py +24 -0
- agent_primitives/failures.py +84 -0
- agent_primitives/py.typed +0 -0
- amb_core/__init__.py +177 -0
- amb_core/adapters/__init__.py +57 -0
- amb_core/adapters/aws_sqs_broker.py +376 -0
- amb_core/adapters/azure_servicebus_broker.py +340 -0
- amb_core/adapters/kafka_broker.py +260 -0
- amb_core/adapters/nats_broker.py +285 -0
- amb_core/adapters/rabbitmq_broker.py +235 -0
- amb_core/adapters/redis_broker.py +262 -0
- amb_core/broker.py +145 -0
- amb_core/bus.py +481 -0
- amb_core/cloudevents.py +509 -0
- amb_core/dlq.py +345 -0
- amb_core/hf_utils.py +536 -0
- amb_core/memory_broker.py +410 -0
- amb_core/models.py +141 -0
- amb_core/persistence.py +529 -0
- amb_core/schema.py +294 -0
- amb_core/tracing.py +358 -0
- atr/__init__.py +640 -0
- atr/access.py +348 -0
- atr/composition.py +645 -0
- atr/decorator.py +357 -0
- atr/executor.py +384 -0
- atr/health.py +557 -0
- atr/hf_utils.py +449 -0
- atr/injection.py +422 -0
- atr/metrics.py +440 -0
- atr/policies.py +403 -0
- atr/py.typed +2 -0
- atr/registry.py +452 -0
- atr/schema.py +480 -0
- atr/tools/safe/__init__.py +75 -0
- atr/tools/safe/calculator.py +467 -0
- atr/tools/safe/datetime_tool.py +443 -0
- atr/tools/safe/file_reader.py +402 -0
- atr/tools/safe/http_client.py +316 -0
- atr/tools/safe/json_parser.py +374 -0
- atr/tools/safe/text_tool.py +537 -0
- atr/tools/safe/toolkit.py +175 -0
- caas/__init__.py +162 -0
- caas/api/__init__.py +7 -0
- caas/api/server.py +1328 -0
- caas/caching.py +834 -0
- caas/cli.py +210 -0
- caas/conversation.py +223 -0
- caas/decay.py +72 -0
- caas/detection/__init__.py +9 -0
- caas/detection/detector.py +238 -0
- caas/enrichment.py +130 -0
- caas/gateway/__init__.py +27 -0
- caas/gateway/trust_gateway.py +474 -0
- caas/hf_utils.py +479 -0
- caas/ingestion/__init__.py +23 -0
- caas/ingestion/processors.py +253 -0
- caas/ingestion/structure_parser.py +188 -0
- caas/models.py +356 -0
- caas/pragmatic_truth.py +444 -0
- caas/routing/__init__.py +10 -0
- caas/routing/heuristic_router.py +58 -0
- caas/storage/__init__.py +9 -0
- caas/storage/store.py +389 -0
- caas/triad.py +213 -0
- caas/tuning/__init__.py +9 -0
- caas/tuning/tuner.py +329 -0
- caas/vfs/__init__.py +14 -0
- caas/vfs/filesystem.py +452 -0
- cmvk/__init__.py +218 -0
- cmvk/audit.py +402 -0
- cmvk/benchmarks.py +478 -0
- cmvk/constitutional.py +904 -0
- cmvk/hf_utils.py +301 -0
- cmvk/metrics.py +473 -0
- cmvk/profiles.py +300 -0
- cmvk/py.typed +0 -0
- cmvk/types.py +12 -0
- cmvk/verification.py +956 -0
- emk/__init__.py +89 -0
- emk/causal.py +352 -0
- emk/hf_utils.py +421 -0
- emk/indexer.py +83 -0
- emk/py.typed +0 -0
- emk/schema.py +204 -0
- emk/sleep_cycle.py +347 -0
- emk/store.py +281 -0
- iatp/__init__.py +166 -0
- iatp/attestation.py +461 -0
- iatp/cli.py +317 -0
- iatp/hf_utils.py +472 -0
- iatp/ipc_pipes.py +580 -0
- iatp/main.py +412 -0
- iatp/models/__init__.py +447 -0
- iatp/policy_engine.py +337 -0
- iatp/py.typed +2 -0
- iatp/recovery.py +321 -0
- iatp/security/__init__.py +270 -0
- iatp/sidecar/__init__.py +519 -0
- iatp/telemetry/__init__.py +164 -0
- iatp/tests/__init__.py +1 -0
- iatp/tests/test_attestation.py +370 -0
- iatp/tests/test_cli.py +131 -0
- iatp/tests/test_ed25519_attestation.py +211 -0
- iatp/tests/test_models.py +130 -0
- iatp/tests/test_policy_engine.py +347 -0
- iatp/tests/test_recovery.py +281 -0
- iatp/tests/test_security.py +222 -0
- iatp/tests/test_sidecar.py +167 -0
- iatp/tests/test_telemetry.py +175 -0
- mcp_kernel_server/__init__.py +28 -0
- mcp_kernel_server/cli.py +274 -0
- mcp_kernel_server/resources.py +217 -0
- mcp_kernel_server/server.py +564 -0
- mcp_kernel_server/tools.py +1174 -0
- mute_agent/__init__.py +68 -0
- mute_agent/core/__init__.py +1 -0
- mute_agent/core/execution_agent.py +166 -0
- mute_agent/core/handshake_protocol.py +201 -0
- mute_agent/core/reasoning_agent.py +238 -0
- mute_agent/knowledge_graph/__init__.py +1 -0
- mute_agent/knowledge_graph/graph_elements.py +65 -0
- mute_agent/knowledge_graph/multidimensional_graph.py +170 -0
- mute_agent/knowledge_graph/subgraph.py +224 -0
- mute_agent/listener/__init__.py +43 -0
- mute_agent/listener/adapters/__init__.py +31 -0
- mute_agent/listener/adapters/base_adapter.py +189 -0
- mute_agent/listener/adapters/caas_adapter.py +344 -0
- mute_agent/listener/adapters/control_plane_adapter.py +436 -0
- mute_agent/listener/adapters/iatp_adapter.py +332 -0
- mute_agent/listener/adapters/scak_adapter.py +251 -0
- mute_agent/listener/listener.py +610 -0
- mute_agent/listener/state_observer.py +436 -0
- mute_agent/listener/threshold_config.py +313 -0
- mute_agent/super_system/__init__.py +1 -0
- mute_agent/super_system/router.py +204 -0
- mute_agent/visualization/__init__.py +10 -0
- mute_agent/visualization/graph_debugger.py +502 -0
- nexus/README.md +60 -0
- nexus/__init__.py +51 -0
- nexus/arbiter.py +359 -0
- nexus/client.py +466 -0
- nexus/dmz.py +444 -0
- nexus/escrow.py +430 -0
- nexus/exceptions.py +286 -0
- nexus/pyproject.toml +36 -0
- nexus/registry.py +393 -0
- nexus/reputation.py +425 -0
- nexus/schemas/__init__.py +51 -0
- nexus/schemas/compliance.py +276 -0
- nexus/schemas/escrow.py +251 -0
- nexus/schemas/manifest.py +225 -0
- nexus/schemas/receipt.py +208 -0
- nexus/tests/__init__.py +0 -0
- nexus/tests/conftest.py +146 -0
- nexus/tests/test_arbiter.py +192 -0
- nexus/tests/test_dmz.py +194 -0
- nexus/tests/test_escrow.py +276 -0
- nexus/tests/test_exceptions.py +225 -0
- nexus/tests/test_registry.py +232 -0
- nexus/tests/test_reputation.py +328 -0
- nexus/tests/test_schemas.py +295 -0
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
# Copyright (c) Microsoft Corporation.
|
|
2
|
+
# Licensed under the MIT License.
|
|
3
|
+
"""
|
|
4
|
+
A2A (Agent-to-Agent) Protocol Adapter - Agent Control Plane Integration
|
|
5
|
+
|
|
6
|
+
This adapter provides governance for A2A protocol communications between agents.
|
|
7
|
+
A2A is an open standard (originally from Google, now Linux Foundation) that enables
|
|
8
|
+
secure interoperability between AI agents from different frameworks and vendors.
|
|
9
|
+
|
|
10
|
+
The A2A adapter intercepts agent-to-agent messages and applies Agent Control Plane
|
|
11
|
+
governance rules to ensure safe and auditable inter-agent communication.
|
|
12
|
+
|
|
13
|
+
Usage:
|
|
14
|
+
from agent_control_plane import AgentControlPlane
|
|
15
|
+
from agent_control_plane.a2a_adapter import A2AAdapter, A2AAgent
|
|
16
|
+
|
|
17
|
+
# Setup control plane
|
|
18
|
+
control_plane = AgentControlPlane()
|
|
19
|
+
agent_context = control_plane.create_agent("my-agent", permissions)
|
|
20
|
+
|
|
21
|
+
# Create governed A2A agent
|
|
22
|
+
a2a_agent = A2AAgent(
|
|
23
|
+
agent_id="my-agent",
|
|
24
|
+
agent_card={
|
|
25
|
+
"name": "My Agent",
|
|
26
|
+
"capabilities": ["data_processing"],
|
|
27
|
+
"description": "An agent that processes data"
|
|
28
|
+
},
|
|
29
|
+
control_plane=control_plane,
|
|
30
|
+
agent_context=agent_context
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
# Register capabilities
|
|
34
|
+
a2a_agent.register_capability("data_processing", handle_data_processing)
|
|
35
|
+
|
|
36
|
+
# All A2A communications are now governed!
|
|
37
|
+
a2a_agent.start()
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
from typing import Any, Dict, List, Optional, Callable, Union
|
|
41
|
+
import json
|
|
42
|
+
import logging
|
|
43
|
+
from datetime import datetime
|
|
44
|
+
from enum import Enum
|
|
45
|
+
import uuid
|
|
46
|
+
|
|
47
|
+
from .agent_kernel import ActionType, AgentContext
|
|
48
|
+
from .control_plane import AgentControlPlane
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class A2AMessageType(Enum):
|
|
52
|
+
"""A2A protocol message types"""
|
|
53
|
+
TASK_REQUEST = "task_request"
|
|
54
|
+
TASK_RESPONSE = "task_response"
|
|
55
|
+
TASK_DELEGATION = "task_delegation"
|
|
56
|
+
QUERY = "query"
|
|
57
|
+
RESPONSE = "response"
|
|
58
|
+
NEGOTIATE = "negotiate"
|
|
59
|
+
HANDSHAKE = "handshake"
|
|
60
|
+
DISCOVERY = "discovery"
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# Mapping from A2A operations to ActionTypes
|
|
64
|
+
DEFAULT_A2A_MAPPING = {
|
|
65
|
+
# Task operations
|
|
66
|
+
"task_request": ActionType.WORKFLOW_TRIGGER,
|
|
67
|
+
"task_delegation": ActionType.WORKFLOW_TRIGGER,
|
|
68
|
+
|
|
69
|
+
# Data operations
|
|
70
|
+
"query": ActionType.DATABASE_QUERY,
|
|
71
|
+
"data_request": ActionType.FILE_READ,
|
|
72
|
+
|
|
73
|
+
# Code/compute operations
|
|
74
|
+
"execute": ActionType.CODE_EXECUTION,
|
|
75
|
+
"compute": ActionType.CODE_EXECUTION,
|
|
76
|
+
|
|
77
|
+
# API/external operations
|
|
78
|
+
"api_call": ActionType.API_CALL,
|
|
79
|
+
"external_request": ActionType.API_CALL,
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class A2AAdapter:
|
|
84
|
+
"""
|
|
85
|
+
A2A Protocol Adapter with Agent Control Plane Governance.
|
|
86
|
+
|
|
87
|
+
This adapter intercepts A2A protocol messages between agents and applies
|
|
88
|
+
governance rules. A2A enables agents to:
|
|
89
|
+
- Discover other agents via Agent Cards
|
|
90
|
+
- Delegate tasks to specialized agents
|
|
91
|
+
- Request information from other agents
|
|
92
|
+
- Coordinate multi-step workflows
|
|
93
|
+
- Negotiate task parameters
|
|
94
|
+
|
|
95
|
+
The adapter ensures all inter-agent communications respect permissions
|
|
96
|
+
and policies defined in the control plane.
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
def __init__(
|
|
100
|
+
self,
|
|
101
|
+
control_plane: AgentControlPlane,
|
|
102
|
+
agent_context: AgentContext,
|
|
103
|
+
agent_card: Dict[str, Any],
|
|
104
|
+
capability_mapping: Optional[Dict[str, ActionType]] = None,
|
|
105
|
+
on_block: Optional[Callable[[str, Dict, Dict], None]] = None,
|
|
106
|
+
logger: Optional[logging.Logger] = None
|
|
107
|
+
):
|
|
108
|
+
"""
|
|
109
|
+
Initialize the A2A adapter.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
control_plane: The AgentControlPlane instance for governance
|
|
113
|
+
agent_context: The AgentContext for this agent
|
|
114
|
+
agent_card: The Agent Card describing this agent's capabilities
|
|
115
|
+
capability_mapping: Optional mapping from capabilities to ActionTypes
|
|
116
|
+
on_block: Optional callback when an action is blocked
|
|
117
|
+
logger: Optional logger instance
|
|
118
|
+
"""
|
|
119
|
+
self.control_plane = control_plane
|
|
120
|
+
self.agent_context = agent_context
|
|
121
|
+
self.agent_card = agent_card
|
|
122
|
+
self.logger = logger or logging.getLogger("A2AAdapter")
|
|
123
|
+
self.on_block = on_block
|
|
124
|
+
|
|
125
|
+
# Merge default mapping with custom mapping
|
|
126
|
+
self.capability_mapping = DEFAULT_A2A_MAPPING.copy()
|
|
127
|
+
if capability_mapping:
|
|
128
|
+
self.capability_mapping.update({k.lower(): v for k, v in capability_mapping.items()})
|
|
129
|
+
|
|
130
|
+
# Track registered capabilities and their handlers
|
|
131
|
+
self.capabilities: Dict[str, Callable] = {}
|
|
132
|
+
|
|
133
|
+
# Track known peer agents (for discovery)
|
|
134
|
+
self.peer_agents: Dict[str, Dict] = {}
|
|
135
|
+
|
|
136
|
+
self.logger.info(
|
|
137
|
+
f"Initialized A2AAdapter for agent {agent_context.agent_id}"
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
def handle_message(self, message: Dict[str, Any], from_agent: str) -> Dict[str, Any]:
|
|
141
|
+
"""
|
|
142
|
+
Handle an A2A protocol message with governance.
|
|
143
|
+
|
|
144
|
+
This is the main entry point for A2A messages from other agents.
|
|
145
|
+
It validates the message, applies governance, and returns a response.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
message: A2A protocol message
|
|
149
|
+
from_agent: ID of the sending agent
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
A2A protocol response
|
|
153
|
+
"""
|
|
154
|
+
msg_type = message.get("type", "")
|
|
155
|
+
msg_id = message.get("id", str(uuid.uuid4()))
|
|
156
|
+
payload = message.get("payload", {})
|
|
157
|
+
|
|
158
|
+
self.logger.debug(f"Received A2A message from {from_agent}: type={msg_type}, id={msg_id}")
|
|
159
|
+
|
|
160
|
+
try:
|
|
161
|
+
# Route to appropriate handler based on message type
|
|
162
|
+
if msg_type == A2AMessageType.TASK_REQUEST.value:
|
|
163
|
+
result = self._handle_task_request(payload, from_agent)
|
|
164
|
+
elif msg_type == A2AMessageType.TASK_DELEGATION.value:
|
|
165
|
+
result = self._handle_task_delegation(payload, from_agent)
|
|
166
|
+
elif msg_type == A2AMessageType.QUERY.value:
|
|
167
|
+
result = self._handle_query(payload, from_agent)
|
|
168
|
+
elif msg_type == A2AMessageType.DISCOVERY.value:
|
|
169
|
+
result = self._handle_discovery(payload, from_agent)
|
|
170
|
+
elif msg_type == A2AMessageType.HANDSHAKE.value:
|
|
171
|
+
result = self._handle_handshake(payload, from_agent)
|
|
172
|
+
elif msg_type == A2AMessageType.NEGOTIATE.value:
|
|
173
|
+
result = self._handle_negotiate(payload, from_agent)
|
|
174
|
+
else:
|
|
175
|
+
return self._create_error_response(msg_id, f"Unknown message type: {msg_type}")
|
|
176
|
+
|
|
177
|
+
# Success response
|
|
178
|
+
return {
|
|
179
|
+
"id": msg_id,
|
|
180
|
+
"type": A2AMessageType.RESPONSE.value,
|
|
181
|
+
"from": self.agent_context.agent_id,
|
|
182
|
+
"to": from_agent,
|
|
183
|
+
"timestamp": datetime.now().isoformat(),
|
|
184
|
+
"payload": result
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
except PermissionError as e:
|
|
188
|
+
# Governance blocked the action
|
|
189
|
+
self.logger.warning(f"Permission denied from {from_agent}: {str(e)}")
|
|
190
|
+
return self._create_error_response(msg_id, str(e))
|
|
191
|
+
|
|
192
|
+
except Exception as e:
|
|
193
|
+
# Other errors
|
|
194
|
+
self.logger.error(f"Error handling A2A message: {str(e)}")
|
|
195
|
+
return self._create_error_response(msg_id, f"Internal error: {str(e)}")
|
|
196
|
+
|
|
197
|
+
def _handle_task_request(self, payload: Dict, from_agent: str) -> Dict:
|
|
198
|
+
"""Handle a task request from another agent."""
|
|
199
|
+
task_type = payload.get("task_type", "")
|
|
200
|
+
task_params = payload.get("parameters", {})
|
|
201
|
+
|
|
202
|
+
self.logger.info(f"Task request from {from_agent}: {task_type}")
|
|
203
|
+
|
|
204
|
+
# Map task type to capability
|
|
205
|
+
capability = task_type.lower()
|
|
206
|
+
|
|
207
|
+
# Check if we have this capability
|
|
208
|
+
if capability not in self.capabilities:
|
|
209
|
+
raise PermissionError(f"Capability not available: {task_type}")
|
|
210
|
+
|
|
211
|
+
# Map to ActionType
|
|
212
|
+
action_type = self._map_capability_to_action(capability)
|
|
213
|
+
|
|
214
|
+
# THE KERNEL CHECK - This is where governance happens
|
|
215
|
+
check_result = self.control_plane.execute_action(
|
|
216
|
+
self.agent_context,
|
|
217
|
+
action_type,
|
|
218
|
+
task_params
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
if not check_result['success']:
|
|
222
|
+
# Action is BLOCKED
|
|
223
|
+
error_msg = f"Task blocked: {check_result.get('error', 'Policy violation')}"
|
|
224
|
+
self.logger.warning(f"BLOCKED: {task_type} from {from_agent} - {error_msg}")
|
|
225
|
+
|
|
226
|
+
if self.on_block:
|
|
227
|
+
self.on_block(task_type, task_params, check_result)
|
|
228
|
+
|
|
229
|
+
raise PermissionError(error_msg)
|
|
230
|
+
|
|
231
|
+
self.logger.info(f"ALLOWED: {task_type} from {from_agent}")
|
|
232
|
+
|
|
233
|
+
# Execute the capability handler
|
|
234
|
+
handler = self.capabilities[capability]
|
|
235
|
+
result = handler(task_params)
|
|
236
|
+
|
|
237
|
+
return {
|
|
238
|
+
"status": "completed",
|
|
239
|
+
"result": result
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
def _handle_task_delegation(self, payload: Dict, from_agent: str) -> Dict:
|
|
243
|
+
"""Handle task delegation (this agent delegating to another)."""
|
|
244
|
+
target_agent = payload.get("target_agent", "")
|
|
245
|
+
task_type = payload.get("task_type", "")
|
|
246
|
+
task_params = payload.get("parameters", {})
|
|
247
|
+
|
|
248
|
+
self.logger.info(f"Task delegation to {target_agent}: {task_type}")
|
|
249
|
+
|
|
250
|
+
# Check if we have permission to delegate tasks
|
|
251
|
+
action_type = ActionType.WORKFLOW_TRIGGER
|
|
252
|
+
|
|
253
|
+
check_result = self.control_plane.execute_action(
|
|
254
|
+
self.agent_context,
|
|
255
|
+
action_type,
|
|
256
|
+
{"target_agent": target_agent, "task_type": task_type}
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
if not check_result['success']:
|
|
260
|
+
error_msg = f"Task delegation blocked: {check_result.get('error', 'Policy violation')}"
|
|
261
|
+
self.logger.warning(f"BLOCKED: delegation to {target_agent} - {error_msg}")
|
|
262
|
+
|
|
263
|
+
if self.on_block:
|
|
264
|
+
self.on_block(task_type, task_params, check_result)
|
|
265
|
+
|
|
266
|
+
raise PermissionError(error_msg)
|
|
267
|
+
|
|
268
|
+
self.logger.info(f"ALLOWED: delegation to {target_agent}")
|
|
269
|
+
|
|
270
|
+
return {
|
|
271
|
+
"status": "delegated",
|
|
272
|
+
"target_agent": target_agent,
|
|
273
|
+
"task_type": task_type
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
def _handle_query(self, payload: Dict, from_agent: str) -> Dict:
|
|
277
|
+
"""Handle a data query from another agent."""
|
|
278
|
+
query_type = payload.get("query_type", "")
|
|
279
|
+
query_params = payload.get("parameters", {})
|
|
280
|
+
|
|
281
|
+
self.logger.info(f"Query from {from_agent}: {query_type}")
|
|
282
|
+
|
|
283
|
+
# Map query to action type
|
|
284
|
+
if "database" in query_type.lower() or "sql" in query_type.lower():
|
|
285
|
+
action_type = ActionType.DATABASE_QUERY
|
|
286
|
+
elif "file" in query_type.lower() or "data" in query_type.lower():
|
|
287
|
+
action_type = ActionType.FILE_READ
|
|
288
|
+
else:
|
|
289
|
+
action_type = ActionType.API_CALL
|
|
290
|
+
|
|
291
|
+
check_result = self.control_plane.execute_action(
|
|
292
|
+
self.agent_context,
|
|
293
|
+
action_type,
|
|
294
|
+
query_params
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
if not check_result['success']:
|
|
298
|
+
error_msg = f"Query blocked: {check_result.get('error', 'Policy violation')}"
|
|
299
|
+
self.logger.warning(f"BLOCKED: {query_type} from {from_agent} - {error_msg}")
|
|
300
|
+
|
|
301
|
+
if self.on_block:
|
|
302
|
+
self.on_block(query_type, query_params, check_result)
|
|
303
|
+
|
|
304
|
+
raise PermissionError(error_msg)
|
|
305
|
+
|
|
306
|
+
self.logger.info(f"ALLOWED: {query_type} from {from_agent}")
|
|
307
|
+
|
|
308
|
+
return {
|
|
309
|
+
"status": "success",
|
|
310
|
+
"data": check_result.get('result', {})
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
def _handle_discovery(self, payload: Dict, from_agent: str) -> Dict:
|
|
314
|
+
"""Handle agent discovery request."""
|
|
315
|
+
self.logger.info(f"Discovery request from {from_agent}")
|
|
316
|
+
|
|
317
|
+
# Discovery is generally safe - return our Agent Card
|
|
318
|
+
return {
|
|
319
|
+
"agent_card": self.agent_card,
|
|
320
|
+
"agent_id": self.agent_context.agent_id
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
def _handle_handshake(self, payload: Dict, from_agent: str) -> Dict:
|
|
324
|
+
"""Handle handshake for establishing connection."""
|
|
325
|
+
self.logger.info(f"Handshake from {from_agent}")
|
|
326
|
+
|
|
327
|
+
# Store peer agent info
|
|
328
|
+
peer_card = payload.get("agent_card", {})
|
|
329
|
+
if peer_card:
|
|
330
|
+
self.peer_agents[from_agent] = peer_card
|
|
331
|
+
|
|
332
|
+
return {
|
|
333
|
+
"status": "connected",
|
|
334
|
+
"agent_card": self.agent_card
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
def _handle_negotiate(self, payload: Dict, from_agent: str) -> Dict:
|
|
338
|
+
"""
|
|
339
|
+
Handle task parameter negotiation.
|
|
340
|
+
|
|
341
|
+
TODO: Implement actual negotiation logic with validation and governance.
|
|
342
|
+
Currently accepts all parameters as a placeholder.
|
|
343
|
+
"""
|
|
344
|
+
self.logger.info(f"Negotiation from {from_agent}")
|
|
345
|
+
|
|
346
|
+
# Negotiation typically involves discussing task parameters
|
|
347
|
+
# Return accepted parameters
|
|
348
|
+
proposed_params = payload.get("parameters", {})
|
|
349
|
+
|
|
350
|
+
return {
|
|
351
|
+
"status": "accepted",
|
|
352
|
+
"parameters": proposed_params
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
def _map_capability_to_action(self, capability: str) -> ActionType:
|
|
356
|
+
"""Map a capability to an ActionType."""
|
|
357
|
+
capability_lower = capability.lower()
|
|
358
|
+
|
|
359
|
+
# Check exact match
|
|
360
|
+
if capability_lower in self.capability_mapping:
|
|
361
|
+
return self.capability_mapping[capability_lower]
|
|
362
|
+
|
|
363
|
+
# Pattern matching
|
|
364
|
+
if any(p in capability_lower for p in ['read', 'get', 'fetch', 'query']):
|
|
365
|
+
if any(p in capability_lower for p in ['file', 'document']):
|
|
366
|
+
return ActionType.FILE_READ
|
|
367
|
+
elif any(p in capability_lower for p in ['database', 'db', 'sql']):
|
|
368
|
+
return ActionType.DATABASE_QUERY
|
|
369
|
+
else:
|
|
370
|
+
return ActionType.API_CALL
|
|
371
|
+
|
|
372
|
+
if any(p in capability_lower for p in ['write', 'save', 'update', 'create']):
|
|
373
|
+
if any(p in capability_lower for p in ['file', 'document']):
|
|
374
|
+
return ActionType.FILE_WRITE
|
|
375
|
+
elif any(p in capability_lower for p in ['database', 'db', 'sql']):
|
|
376
|
+
return ActionType.DATABASE_WRITE
|
|
377
|
+
|
|
378
|
+
if any(p in capability_lower for p in ['execute', 'run', 'compute', 'process']):
|
|
379
|
+
return ActionType.CODE_EXECUTION
|
|
380
|
+
|
|
381
|
+
if any(p in capability_lower for p in ['workflow', 'task', 'delegate']):
|
|
382
|
+
return ActionType.WORKFLOW_TRIGGER
|
|
383
|
+
|
|
384
|
+
# Default to workflow trigger for unknown capabilities
|
|
385
|
+
return ActionType.WORKFLOW_TRIGGER
|
|
386
|
+
|
|
387
|
+
def _create_error_response(self, msg_id: str, error_message: str) -> Dict:
|
|
388
|
+
"""Create an A2A error response."""
|
|
389
|
+
return {
|
|
390
|
+
"id": msg_id,
|
|
391
|
+
"type": "error",
|
|
392
|
+
"from": self.agent_context.agent_id,
|
|
393
|
+
"timestamp": datetime.now().isoformat(),
|
|
394
|
+
"error": {
|
|
395
|
+
"message": error_message
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
def register_capability(self, capability: str, handler: Callable):
|
|
400
|
+
"""
|
|
401
|
+
Register a capability that this agent can perform.
|
|
402
|
+
|
|
403
|
+
Args:
|
|
404
|
+
capability: Name of the capability
|
|
405
|
+
handler: Function to handle requests for this capability
|
|
406
|
+
"""
|
|
407
|
+
self.capabilities[capability.lower()] = handler
|
|
408
|
+
self.logger.debug(f"Registered capability: {capability}")
|
|
409
|
+
|
|
410
|
+
# Update Agent Card
|
|
411
|
+
if "capabilities" not in self.agent_card:
|
|
412
|
+
self.agent_card["capabilities"] = []
|
|
413
|
+
if capability not in self.agent_card["capabilities"]:
|
|
414
|
+
self.agent_card["capabilities"].append(capability)
|
|
415
|
+
|
|
416
|
+
def add_capability_mapping(self, capability: str, action_type: ActionType):
|
|
417
|
+
"""Add a custom capability to ActionType mapping."""
|
|
418
|
+
self.capability_mapping[capability.lower()] = action_type
|
|
419
|
+
self.logger.debug(f"Added capability mapping: {capability} -> {action_type.value}")
|
|
420
|
+
|
|
421
|
+
def get_agent_card(self) -> Dict:
|
|
422
|
+
"""Get this agent's Agent Card for discovery."""
|
|
423
|
+
return {
|
|
424
|
+
**self.agent_card,
|
|
425
|
+
"agent_id": self.agent_context.agent_id,
|
|
426
|
+
"capabilities": list(self.capabilities.keys())
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
def discover_agents(self) -> List[Dict]:
|
|
430
|
+
"""Get list of discovered peer agents."""
|
|
431
|
+
return [
|
|
432
|
+
{"agent_id": agent_id, **card}
|
|
433
|
+
for agent_id, card in self.peer_agents.items()
|
|
434
|
+
]
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
class A2AAgent:
|
|
438
|
+
"""
|
|
439
|
+
Simplified A2A Agent with built-in governance.
|
|
440
|
+
|
|
441
|
+
This class provides a simple way to create an A2A-compliant agent
|
|
442
|
+
with Agent Control Plane governance built in.
|
|
443
|
+
"""
|
|
444
|
+
|
|
445
|
+
def __init__(
|
|
446
|
+
self,
|
|
447
|
+
agent_id: str,
|
|
448
|
+
control_plane: AgentControlPlane,
|
|
449
|
+
agent_context: AgentContext,
|
|
450
|
+
agent_card: Optional[Dict[str, Any]] = None,
|
|
451
|
+
logger: Optional[logging.Logger] = None
|
|
452
|
+
):
|
|
453
|
+
"""
|
|
454
|
+
Initialize an A2A agent.
|
|
455
|
+
|
|
456
|
+
Args:
|
|
457
|
+
agent_id: Unique identifier for this agent
|
|
458
|
+
control_plane: Agent Control Plane instance
|
|
459
|
+
agent_context: Agent context
|
|
460
|
+
agent_card: Optional Agent Card (description, capabilities, etc.)
|
|
461
|
+
logger: Optional logger
|
|
462
|
+
"""
|
|
463
|
+
self.agent_id = agent_id
|
|
464
|
+
self.logger = logger or logging.getLogger(f"A2AAgent.{agent_id}")
|
|
465
|
+
|
|
466
|
+
# Create default Agent Card if not provided
|
|
467
|
+
if agent_card is None:
|
|
468
|
+
agent_card = {
|
|
469
|
+
"name": agent_id,
|
|
470
|
+
"description": f"Agent {agent_id}",
|
|
471
|
+
"version": "1.0.0",
|
|
472
|
+
"capabilities": []
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
# Create the adapter
|
|
476
|
+
self.adapter = A2AAdapter(
|
|
477
|
+
control_plane=control_plane,
|
|
478
|
+
agent_context=agent_context,
|
|
479
|
+
agent_card=agent_card,
|
|
480
|
+
logger=self.logger
|
|
481
|
+
)
|
|
482
|
+
|
|
483
|
+
self.logger.info(f"Initialized A2A agent: {agent_id}")
|
|
484
|
+
|
|
485
|
+
def register_capability(self, capability: str, handler: Callable):
|
|
486
|
+
"""Register a capability with the agent."""
|
|
487
|
+
self.adapter.register_capability(capability, handler)
|
|
488
|
+
|
|
489
|
+
def handle_message(self, message: Dict, from_agent: str) -> Dict:
|
|
490
|
+
"""Handle an A2A message."""
|
|
491
|
+
return self.adapter.handle_message(message, from_agent)
|
|
492
|
+
|
|
493
|
+
def send_task_request(self, to_agent: str, task_type: str, parameters: Dict) -> Dict:
|
|
494
|
+
"""Send a task request to another agent."""
|
|
495
|
+
message = {
|
|
496
|
+
"id": str(uuid.uuid4()),
|
|
497
|
+
"type": A2AMessageType.TASK_REQUEST.value,
|
|
498
|
+
"from": self.agent_id,
|
|
499
|
+
"to": to_agent,
|
|
500
|
+
"timestamp": datetime.now().isoformat(),
|
|
501
|
+
"payload": {
|
|
502
|
+
"task_type": task_type,
|
|
503
|
+
"parameters": parameters
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
self.logger.info(f"Sending task request to {to_agent}: {task_type}")
|
|
507
|
+
return message
|
|
508
|
+
|
|
509
|
+
def get_agent_card(self) -> Dict:
|
|
510
|
+
"""Get this agent's Agent Card."""
|
|
511
|
+
return self.adapter.get_agent_card()
|
|
512
|
+
|
|
513
|
+
def start(self):
|
|
514
|
+
"""Start the A2A agent (placeholder for actual implementation)."""
|
|
515
|
+
self.logger.info(f"A2A agent '{self.agent_id}' started")
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
def create_governed_a2a_agent(
|
|
519
|
+
control_plane: AgentControlPlane,
|
|
520
|
+
agent_id: str,
|
|
521
|
+
agent_card: Optional[Dict[str, Any]] = None,
|
|
522
|
+
permissions: Optional[Dict[ActionType, Any]] = None
|
|
523
|
+
) -> A2AAgent:
|
|
524
|
+
"""
|
|
525
|
+
Convenience function to create a governed A2A agent.
|
|
526
|
+
|
|
527
|
+
Args:
|
|
528
|
+
control_plane: Agent Control Plane instance
|
|
529
|
+
agent_id: Agent ID
|
|
530
|
+
agent_card: Optional Agent Card
|
|
531
|
+
permissions: Optional agent permissions
|
|
532
|
+
|
|
533
|
+
Returns:
|
|
534
|
+
A governed A2AAgent instance
|
|
535
|
+
"""
|
|
536
|
+
agent_context = control_plane.create_agent(agent_id, permissions)
|
|
537
|
+
|
|
538
|
+
return A2AAgent(
|
|
539
|
+
agent_id=agent_id,
|
|
540
|
+
control_plane=control_plane,
|
|
541
|
+
agent_context=agent_context,
|
|
542
|
+
agent_card=agent_card
|
|
543
|
+
)
|