agenttrustid 0.3.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.
- agenttrustid/__init__.py +100 -0
- agenttrustid/a2a.py +158 -0
- agenttrustid/agentcard.py +87 -0
- agenttrustid/autogen_callback.py +561 -0
- agenttrustid/callback.py +229 -0
- agenttrustid/client.py +703 -0
- agenttrustid/crewai_callback.py +379 -0
- agenttrustid/delegation.py +107 -0
- agenttrustid/exceptions.py +41 -0
- agenttrustid/federation.py +75 -0
- agenttrustid/guard.py +133 -0
- agenttrustid/mcp_client.py +127 -0
- agenttrustid/models.py +578 -0
- agenttrustid/streaming.py +94 -0
- agenttrustid/telemetry.py +128 -0
- agenttrustid-0.3.0.dist-info/METADATA +423 -0
- agenttrustid-0.3.0.dist-info/RECORD +20 -0
- agenttrustid-0.3.0.dist-info/WHEEL +5 -0
- agenttrustid-0.3.0.dist-info/licenses/LICENSE +201 -0
- agenttrustid-0.3.0.dist-info/top_level.txt +1 -0
agenttrustid/__init__.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AgentTrust SDK - Authentication, authorization, and runtime security for AI agents.
|
|
3
|
+
|
|
4
|
+
Quick Start:
|
|
5
|
+
from agenttrustid import AgentTrustClient
|
|
6
|
+
|
|
7
|
+
# Initialize with gateway URL and API key
|
|
8
|
+
client = AgentTrustClient(base_url="http://localhost:8080", api_key="sk_live_xxx")
|
|
9
|
+
|
|
10
|
+
# Create an agent
|
|
11
|
+
agent = client.agents.create(name="my-agent", framework="langchain")
|
|
12
|
+
|
|
13
|
+
# LangChain integration (pip install agenttrustid[langchain])
|
|
14
|
+
from agenttrustid.callback import AgentTrustCallbackHandler
|
|
15
|
+
handler = AgentTrustCallbackHandler(client, agent_id=agent.id)
|
|
16
|
+
agent_executor.invoke({"input": "..."}, config={"callbacks": [handler]})
|
|
17
|
+
|
|
18
|
+
# CrewAI integration
|
|
19
|
+
from agenttrustid.crewai_callback import AgentTrustCrewAIToolWrapper, agenttrust_protect_crew
|
|
20
|
+
|
|
21
|
+
# AutoGen integration
|
|
22
|
+
from agenttrustid.autogen_callback import AgentTrustAutoGenToolWrapper, agenttrust_wrap_tool
|
|
23
|
+
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from .client import AgentTrustClient
|
|
27
|
+
from .models import (
|
|
28
|
+
Agent,
|
|
29
|
+
Token,
|
|
30
|
+
IntrospectionResult,
|
|
31
|
+
VerificationResult,
|
|
32
|
+
ActionCheckResult,
|
|
33
|
+
AgentCard,
|
|
34
|
+
A2ATask,
|
|
35
|
+
A2AMessageTask,
|
|
36
|
+
MCPServer,
|
|
37
|
+
Delegation,
|
|
38
|
+
Session,
|
|
39
|
+
ApprovalRequest,
|
|
40
|
+
FederationProvider,
|
|
41
|
+
FederationIntrospectionResult,
|
|
42
|
+
VerifyFederatedTokenResult,
|
|
43
|
+
SIEMDestination,
|
|
44
|
+
SIEMDeliveryRecord,
|
|
45
|
+
)
|
|
46
|
+
from .a2a import A2AAPI
|
|
47
|
+
from .agentcard import AgentCardsAPI
|
|
48
|
+
from .mcp_client import MCPAPI
|
|
49
|
+
from .delegation import DelegationsAPI
|
|
50
|
+
from .federation import FederationAPI
|
|
51
|
+
from .streaming import StreamingAPI
|
|
52
|
+
from .client import SessionsAPI, ApprovalsAPI
|
|
53
|
+
from .guard import AgentTrustGuard
|
|
54
|
+
from .exceptions import (
|
|
55
|
+
AgentTrustError,
|
|
56
|
+
AuthenticationError,
|
|
57
|
+
AuthorizationError,
|
|
58
|
+
TokenExpiredError,
|
|
59
|
+
AgentRevokedError,
|
|
60
|
+
NetworkError,
|
|
61
|
+
ValidationError,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
__version__ = "0.3.0"
|
|
65
|
+
__all__ = [
|
|
66
|
+
"AgentTrustClient",
|
|
67
|
+
"AgentTrustGuard",
|
|
68
|
+
"Agent",
|
|
69
|
+
"Token",
|
|
70
|
+
"IntrospectionResult",
|
|
71
|
+
"VerificationResult",
|
|
72
|
+
"ActionCheckResult",
|
|
73
|
+
"AgentCard",
|
|
74
|
+
"A2ATask",
|
|
75
|
+
"A2AMessageTask",
|
|
76
|
+
"MCPServer",
|
|
77
|
+
"Delegation",
|
|
78
|
+
"Session",
|
|
79
|
+
"ApprovalRequest",
|
|
80
|
+
"FederationProvider",
|
|
81
|
+
"FederationIntrospectionResult",
|
|
82
|
+
"VerifyFederatedTokenResult",
|
|
83
|
+
"SIEMDestination",
|
|
84
|
+
"SIEMDeliveryRecord",
|
|
85
|
+
"A2AAPI",
|
|
86
|
+
"AgentCardsAPI",
|
|
87
|
+
"MCPAPI",
|
|
88
|
+
"DelegationsAPI",
|
|
89
|
+
"FederationAPI",
|
|
90
|
+
"StreamingAPI",
|
|
91
|
+
"SessionsAPI",
|
|
92
|
+
"ApprovalsAPI",
|
|
93
|
+
"AgentTrustError",
|
|
94
|
+
"AuthenticationError",
|
|
95
|
+
"AuthorizationError",
|
|
96
|
+
"TokenExpiredError",
|
|
97
|
+
"AgentRevokedError",
|
|
98
|
+
"NetworkError",
|
|
99
|
+
"ValidationError",
|
|
100
|
+
]
|
agenttrustid/a2a.py
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"""AgentTrust SDK A2A (Agent-to-Agent) Task Management"""
|
|
2
|
+
|
|
3
|
+
import uuid
|
|
4
|
+
from typing import Dict, List, Optional
|
|
5
|
+
|
|
6
|
+
from .models import A2ATask, A2AMessageTask
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class A2AAPI:
|
|
10
|
+
"""A2A task management API.
|
|
11
|
+
|
|
12
|
+
Enables agent-to-agent communication through the A2A protocol.
|
|
13
|
+
Tasks are dispatched via JSON-RPC through the /a2a endpoint.
|
|
14
|
+
|
|
15
|
+
Example:
|
|
16
|
+
# Send a task from one agent to another
|
|
17
|
+
task = client.a2a.send_task(
|
|
18
|
+
source_agent_id="agent-123",
|
|
19
|
+
target_agent_id="agent-456",
|
|
20
|
+
message="Summarize the latest security report",
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
# Check task status
|
|
24
|
+
task = client.a2a.get_task(task.id)
|
|
25
|
+
|
|
26
|
+
# Cancel if needed
|
|
27
|
+
client.a2a.cancel_task(task.id)
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def __init__(self, http_client):
|
|
31
|
+
self._http = http_client
|
|
32
|
+
|
|
33
|
+
def _jsonrpc_request(self, method: str, params: dict, path: str = "/a2a") -> dict:
|
|
34
|
+
"""Send a JSON-RPC request to an A2A endpoint.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
method: JSON-RPC method name (e.g., "tasks/send")
|
|
38
|
+
params: Method parameters
|
|
39
|
+
path: Endpoint to POST to. Defaults to the shared ``/a2a``
|
|
40
|
+
endpoint; ``message/send`` targets the per-agent endpoint
|
|
41
|
+
``/a2a/agents/{agent_id}`` so the server resolves the actor
|
|
42
|
+
from the path.
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
The "result" field from the JSON-RPC response
|
|
46
|
+
"""
|
|
47
|
+
payload = {
|
|
48
|
+
"jsonrpc": "2.0",
|
|
49
|
+
"id": 1,
|
|
50
|
+
"method": method,
|
|
51
|
+
"params": params,
|
|
52
|
+
}
|
|
53
|
+
response = self._http.post(path, payload)
|
|
54
|
+
# JSON-RPC responses have the result nested under "result"
|
|
55
|
+
if "result" in response:
|
|
56
|
+
return response["result"]
|
|
57
|
+
return response
|
|
58
|
+
|
|
59
|
+
def send_task(
|
|
60
|
+
self,
|
|
61
|
+
source_agent_id: str,
|
|
62
|
+
target_agent_id: str,
|
|
63
|
+
message: str,
|
|
64
|
+
metadata: Optional[Dict] = None,
|
|
65
|
+
) -> A2ATask:
|
|
66
|
+
"""
|
|
67
|
+
Send a task from one agent to another.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
source_agent_id: ID of the agent sending the task
|
|
71
|
+
target_agent_id: ID of the agent receiving the task
|
|
72
|
+
message: Task message/instruction for the target agent
|
|
73
|
+
metadata: Optional metadata to attach to the task
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
A2ATask with the created task details
|
|
77
|
+
"""
|
|
78
|
+
params = {
|
|
79
|
+
"source_agent_id": source_agent_id,
|
|
80
|
+
"target_agent_id": target_agent_id,
|
|
81
|
+
"message": message,
|
|
82
|
+
}
|
|
83
|
+
if metadata:
|
|
84
|
+
params["metadata"] = metadata
|
|
85
|
+
|
|
86
|
+
result = self._jsonrpc_request("tasks/send", params)
|
|
87
|
+
return A2ATask.from_dict(result)
|
|
88
|
+
|
|
89
|
+
def get_task(self, task_id: str) -> A2ATask:
|
|
90
|
+
"""
|
|
91
|
+
Get the current status and details of a task.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
task_id: ID of the task to retrieve
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
A2ATask with current task state
|
|
98
|
+
"""
|
|
99
|
+
result = self._jsonrpc_request("tasks/get", {"task_id": task_id})
|
|
100
|
+
return A2ATask.from_dict(result)
|
|
101
|
+
|
|
102
|
+
def cancel_task(self, task_id: str) -> A2ATask:
|
|
103
|
+
"""
|
|
104
|
+
Cancel a pending or in-progress task.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
task_id: ID of the task to cancel
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
A2ATask with updated (cancelled) status
|
|
111
|
+
"""
|
|
112
|
+
result = self._jsonrpc_request("tasks/cancel", {"task_id": task_id})
|
|
113
|
+
return A2ATask.from_dict(result)
|
|
114
|
+
|
|
115
|
+
def send_message(
|
|
116
|
+
self,
|
|
117
|
+
agent_id: str,
|
|
118
|
+
text: str,
|
|
119
|
+
message_id: Optional[str] = None,
|
|
120
|
+
task_id: Optional[str] = None,
|
|
121
|
+
) -> A2AMessageTask:
|
|
122
|
+
"""
|
|
123
|
+
Send a message to an agent using the A2A v1.0 ``message/send`` method.
|
|
124
|
+
|
|
125
|
+
Dispatches a JSON-RPC ``message/send`` call to the target agent's
|
|
126
|
+
per-agent endpoint ``/a2a/agents/{agent_id}`` (mirroring the other
|
|
127
|
+
SDKs) so the server resolves the actor from the path. The message
|
|
128
|
+
follows the v1.0 schema with a text part. A new ``messageId`` is
|
|
129
|
+
generated when one is not supplied. If ``task_id`` is given, the
|
|
130
|
+
message is attached to that existing task.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
agent_id: ID of the target agent.
|
|
134
|
+
text: The text content of the message.
|
|
135
|
+
message_id: Optional client-supplied message ID (a UUID is
|
|
136
|
+
generated when omitted).
|
|
137
|
+
task_id: Optional existing task ID to continue.
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
A2AMessageTask parsed from the v1.0 Task result
|
|
141
|
+
``{id, contextId, status: {state, timestamp}, history?, artifacts?}``.
|
|
142
|
+
"""
|
|
143
|
+
message: Dict = {
|
|
144
|
+
"role": "user",
|
|
145
|
+
"parts": [{"kind": "text", "text": text}],
|
|
146
|
+
"messageId": message_id or str(uuid.uuid4()),
|
|
147
|
+
}
|
|
148
|
+
if task_id:
|
|
149
|
+
message["taskId"] = task_id
|
|
150
|
+
|
|
151
|
+
# Post to the per-agent endpoint; the server authorizes message/send
|
|
152
|
+
# from the path agent, not a params field. Params carry only the
|
|
153
|
+
# message, matching the Go/TS/Java/Rust SDKs.
|
|
154
|
+
params = {"message": message}
|
|
155
|
+
result = self._jsonrpc_request(
|
|
156
|
+
"message/send", params, path=f"/a2a/agents/{agent_id}"
|
|
157
|
+
)
|
|
158
|
+
return A2AMessageTask.from_dict(result)
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""AgentTrust SDK Agent Card Management"""
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from .models import AgentCard
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AgentCardsAPI:
|
|
9
|
+
"""Agent Card management API.
|
|
10
|
+
|
|
11
|
+
Agent Cards provide standardized metadata about an agent's identity,
|
|
12
|
+
capabilities, supported interfaces, and skills following the A2A
|
|
13
|
+
protocol v1.0. Cards are parsed into :class:`AgentCard`; use
|
|
14
|
+
``card.primary_url`` and ``card.trust_score`` to read the endpoint and
|
|
15
|
+
ATI trust extension.
|
|
16
|
+
|
|
17
|
+
Example:
|
|
18
|
+
# Generate and publish a card
|
|
19
|
+
card = client.agent_cards.generate(agent_id="agent-123")
|
|
20
|
+
client.agent_cards.publish(agent_id="agent-123")
|
|
21
|
+
|
|
22
|
+
# Retrieve the public card (no auth required)
|
|
23
|
+
public_card = client.agent_cards.get_public(agent_id="agent-123")
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(self, http_client):
|
|
27
|
+
self._http = http_client
|
|
28
|
+
|
|
29
|
+
def generate(self, agent_id: str) -> AgentCard:
|
|
30
|
+
"""
|
|
31
|
+
Generate an Agent Card for the given agent.
|
|
32
|
+
|
|
33
|
+
Creates or regenerates the agent's card with current metadata,
|
|
34
|
+
capabilities, and security policy information.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
agent_id: ID of the agent to generate a card for
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
AgentCard with the generated card data
|
|
41
|
+
"""
|
|
42
|
+
result = self._http.post(f"/api/v1/agents/{agent_id}/card")
|
|
43
|
+
return AgentCard.from_dict(result)
|
|
44
|
+
|
|
45
|
+
def get(self, agent_id: str) -> AgentCard:
|
|
46
|
+
"""
|
|
47
|
+
Get the Agent Card for the given agent.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
agent_id: ID of the agent
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
AgentCard with current card data
|
|
54
|
+
"""
|
|
55
|
+
result = self._http.get(f"/api/v1/agents/{agent_id}/card")
|
|
56
|
+
return AgentCard.from_dict(result)
|
|
57
|
+
|
|
58
|
+
def publish(self, agent_id: str) -> AgentCard:
|
|
59
|
+
"""
|
|
60
|
+
Publish the agent's card, making it publicly discoverable.
|
|
61
|
+
|
|
62
|
+
Once published, the card is available at the well-known URL
|
|
63
|
+
and can be discovered by other agents via A2A protocol.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
agent_id: ID of the agent
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
AgentCard with updated publish status
|
|
70
|
+
"""
|
|
71
|
+
result = self._http.put(f"/api/v1/agents/{agent_id}/card/publish")
|
|
72
|
+
return AgentCard.from_dict(result)
|
|
73
|
+
|
|
74
|
+
def get_public(self, agent_id: str) -> AgentCard:
|
|
75
|
+
"""
|
|
76
|
+
Get the publicly published Agent Card (no authentication required).
|
|
77
|
+
|
|
78
|
+
This uses the well-known A2A discovery path.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
agent_id: ID of the agent
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
AgentCard with public card data
|
|
85
|
+
"""
|
|
86
|
+
result = self._http.get(f"/a2a/agents/{agent_id}/agent.json")
|
|
87
|
+
return AgentCard.from_dict(result)
|