agentex-sdk 0.1.1__py3-none-any.whl → 0.2.1__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.
- agentex/_version.py +1 -1
- agentex/lib/adk/_modules/messages.py +2 -2
- agentex/lib/adk/_modules/streaming.py +2 -2
- agentex/lib/adk/providers/_modules/litellm.py +2 -2
- agentex/lib/adk/providers/_modules/openai.py +2 -2
- agentex/lib/cli/commands/init.py +8 -4
- agentex/lib/cli/handlers/deploy_handlers.py +20 -0
- agentex/lib/cli/handlers/run_handlers.py +7 -0
- agentex/lib/cli/templates/default/README.md.j2 +23 -2
- agentex/lib/cli/templates/default/dev.ipynb.j2 +127 -0
- agentex/lib/cli/templates/sync/README.md.j2 +22 -2
- agentex/lib/cli/templates/sync/dev.ipynb.j2 +181 -0
- agentex/lib/cli/templates/sync/project/acp.py.j2 +63 -14
- agentex/lib/cli/templates/temporal/README.md.j2 +24 -3
- agentex/lib/cli/templates/temporal/dev.ipynb.j2 +127 -0
- agentex/lib/cli/templates/temporal/project/workflow.py.j2 +1 -1
- agentex/lib/cli/utils/__init__.py +0 -0
- agentex/lib/cli/utils/auth_utils.py +18 -0
- agentex/lib/core/adapters/streams/adapter_redis.py +4 -4
- agentex/lib/core/adapters/streams/port.py +1 -1
- agentex/lib/core/services/adk/streaming.py +2 -3
- agentex/lib/core/temporal/activities/__init__.py +2 -2
- agentex/lib/environment_variables.py +4 -1
- agentex/lib/sdk/config/agent_manifest.py +2 -1
- agentex/lib/sdk/config/deployment_config.py +5 -1
- agentex/lib/sdk/fastacp/base/base_acp_server.py +14 -0
- agentex/lib/utils/dev_tools/__init__.py +9 -0
- agentex/lib/utils/dev_tools/async_messages.py +386 -0
- agentex/resources/agents.py +5 -6
- agentex/types/agent_rpc_by_name_params.py +55 -5
- agentex/types/agent_rpc_params.py +27 -7
- {agentex_sdk-0.1.1.dist-info → agentex_sdk-0.2.1.dist-info}/METADATA +1 -1
- {agentex_sdk-0.1.1.dist-info → agentex_sdk-0.2.1.dist-info}/RECORD +36 -30
- agentex/types/agent_rpc_params1.py +0 -21
- {agentex_sdk-0.1.1.dist-info → agentex_sdk-0.2.1.dist-info}/WHEEL +0 -0
- {agentex_sdk-0.1.1.dist-info → agentex_sdk-0.2.1.dist-info}/entry_points.txt +0 -0
- {agentex_sdk-0.1.1.dist-info → agentex_sdk-0.2.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,26 +1,75 @@
|
|
1
|
-
|
1
|
+
import json
|
2
|
+
from agentex.lib import adk
|
2
3
|
from agentex.lib.sdk.fastacp.fastacp import FastACP
|
3
|
-
from agentex.lib.types.
|
4
|
+
from agentex.lib.types.fastacp import AgenticACPConfig
|
5
|
+
from agentex.lib.types.acp import CancelTaskParams, CreateTaskParams, SendEventParams
|
4
6
|
|
5
|
-
from agentex.lib.types.task_message_updates import TaskMessageUpdate
|
6
|
-
from agentex.types.task_message_content import TaskMessageContent
|
7
7
|
from agentex.types.text_content import TextContent
|
8
8
|
from agentex.lib.utils.logging import make_logger
|
9
9
|
|
10
10
|
logger = make_logger(__name__)
|
11
11
|
|
12
12
|
|
13
|
-
# Create an ACP server
|
13
|
+
# Create an ACP server with base configuration
|
14
|
+
# This sets up the core server that will handle task creation, events, and cancellation
|
14
15
|
acp = FastACP.create(
|
15
|
-
acp_type="
|
16
|
+
acp_type="agentic",
|
17
|
+
config=AgenticACPConfig(
|
18
|
+
type="base",
|
19
|
+
),
|
16
20
|
)
|
17
21
|
|
18
|
-
@acp.
|
19
|
-
async def
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
@acp.on_task_create
|
23
|
+
async def handle_task_create(params: CreateTaskParams):
|
24
|
+
# This handler is called first whenever a new task is created.
|
25
|
+
# It's a good place to initialize any state or resources needed for the task.
|
26
|
+
|
27
|
+
#########################################################
|
28
|
+
# 1. (👋) Do task initialization here.
|
29
|
+
#########################################################
|
30
|
+
|
31
|
+
# Acknowledge that the task has been created.
|
32
|
+
await adk.messages.create(
|
33
|
+
task_id=params.task.id,
|
34
|
+
content=TextContent(
|
35
|
+
author="agent",
|
36
|
+
content=f"Hello! I've received your task. Normally you can do some state initialization here, or just pass and do nothing until you get your first event. For now I'm just acknowledging that I've received a task with the following params:\n\n{json.dumps(params.params, indent=2)}.\n\nYou should only see this message once, when the task is created. All subsequent events will be handled by the `on_task_event_send` handler.",
|
37
|
+
),
|
26
38
|
)
|
39
|
+
|
40
|
+
@acp.on_task_event_send
|
41
|
+
async def handle_event_send(params: SendEventParams):
|
42
|
+
# This handler is called whenever a new event (like a message) is sent to the task
|
43
|
+
|
44
|
+
#########################################################
|
45
|
+
# 2. (👋) Echo back the client's message to show it in the UI.
|
46
|
+
#########################################################
|
47
|
+
|
48
|
+
# This is not done by default so the agent developer has full control over what is shown to the user.
|
49
|
+
if params.event.content:
|
50
|
+
await adk.messages.create(task_id=params.task.id, content=params.event.content)
|
51
|
+
|
52
|
+
#########################################################
|
53
|
+
# 3. (👋) Send a simple response message.
|
54
|
+
#########################################################
|
55
|
+
|
56
|
+
# In future tutorials, this is where we'll add more sophisticated response logic.
|
57
|
+
await adk.messages.create(
|
58
|
+
task_id=params.task.id,
|
59
|
+
content=TextContent(
|
60
|
+
author="agent",
|
61
|
+
content=f"Hello! I've received your message. I can't respond right now, but in future tutorials we'll see how you can get me to intelligently respond to your message.",
|
62
|
+
),
|
63
|
+
)
|
64
|
+
|
65
|
+
@acp.on_task_cancel
|
66
|
+
async def handle_task_cancel(params: CancelTaskParams):
|
67
|
+
# This handler is called when a task is cancelled.
|
68
|
+
# It's useful for cleaning up any resources or state associated with the task.
|
69
|
+
|
70
|
+
#########################################################
|
71
|
+
# 4. (👋) Do task cleanup here.
|
72
|
+
#########################################################
|
73
|
+
|
74
|
+
# This is mostly for durable workflows that are cancellable like Temporal, but we will leave it here for demonstration purposes.
|
75
|
+
logger.info(f"Hello! I've received task cancel for task {params.task.id}: {params.task}. This isn't necessary for this example, but it's good to know that it's available.")
|
@@ -68,6 +68,7 @@ This file is essential for both local development and deployment of your agent.
|
|
68
68
|
│ └── run_worker.py # Temporal worker setup
|
69
69
|
├── Dockerfile # Container definition
|
70
70
|
├── manifest.yaml # Deployment config
|
71
|
+
├── dev.ipynb # Development notebook for testing
|
71
72
|
{% if use_uv %}
|
72
73
|
└── pyproject.toml # Dependencies (uv)
|
73
74
|
{% else %}
|
@@ -82,12 +83,32 @@ This file is essential for both local development and deployment of your agent.
|
|
82
83
|
- Add your own tools and capabilities
|
83
84
|
- Implement custom state management
|
84
85
|
|
85
|
-
### 2.
|
86
|
+
### 2. Test Your Agent with the Development Notebook
|
87
|
+
Use the included `dev.ipynb` Jupyter notebook to test your agent interactively:
|
88
|
+
|
89
|
+
```bash
|
90
|
+
# Start Jupyter notebook (make sure you have jupyter installed)
|
91
|
+
jupyter notebook dev.ipynb
|
92
|
+
|
93
|
+
# Or use VS Code to open the notebook directly
|
94
|
+
code dev.ipynb
|
95
|
+
```
|
96
|
+
|
97
|
+
The notebook includes:
|
98
|
+
- **Setup**: Connect to your local AgentEx backend
|
99
|
+
- **Task creation**: Create a new task for the conversation
|
100
|
+
- **Event sending**: Send events to the agent and get responses
|
101
|
+
- **Async message subscription**: Subscribe to server-side events to receive agent responses
|
102
|
+
- **Rich message display**: Beautiful formatting with timestamps and author information
|
103
|
+
|
104
|
+
The notebook automatically uses your agent name (`{{ agent_name }}`) and demonstrates the agentic ACP workflow: create task → send event → subscribe to responses.
|
105
|
+
|
106
|
+
### 3. Develop Temporal Workflows
|
86
107
|
- Edit `workflow.py` to define your agent's async workflow logic
|
87
108
|
- Modify `activities.py` to add custom activities
|
88
109
|
- Use `run_worker.py` to configure the Temporal worker
|
89
110
|
|
90
|
-
###
|
111
|
+
### 4. Manage Dependencies
|
91
112
|
|
92
113
|
{% if use_uv %}
|
93
114
|
You chose **uv** for package management. Here's how to work with dependencies:
|
@@ -135,7 +156,7 @@ pip install -r requirements.txt
|
|
135
156
|
- Wide compatibility
|
136
157
|
{% endif %}
|
137
158
|
|
138
|
-
###
|
159
|
+
### 5. Configure Credentials
|
139
160
|
- Add any required credentials to your manifest.yaml
|
140
161
|
- For local development, create a `.env` file in the project directory
|
141
162
|
- Use `load_dotenv()` only in development mode:
|
@@ -0,0 +1,127 @@
|
|
1
|
+
{
|
2
|
+
"cells": [
|
3
|
+
{
|
4
|
+
"cell_type": "code",
|
5
|
+
"execution_count": null,
|
6
|
+
"id": "36834357",
|
7
|
+
"metadata": {},
|
8
|
+
"outputs": [],
|
9
|
+
"source": [
|
10
|
+
"from agentex import Agentex\n",
|
11
|
+
"\n",
|
12
|
+
"client = Agentex(base_url=\"http://localhost:5003\")"
|
13
|
+
]
|
14
|
+
},
|
15
|
+
{
|
16
|
+
"cell_type": "code",
|
17
|
+
"execution_count": null,
|
18
|
+
"id": "d1c309d6",
|
19
|
+
"metadata": {},
|
20
|
+
"outputs": [],
|
21
|
+
"source": [
|
22
|
+
"AGENT_NAME = \"{{ agent_name }}\""
|
23
|
+
]
|
24
|
+
},
|
25
|
+
{
|
26
|
+
"cell_type": "code",
|
27
|
+
"execution_count": null,
|
28
|
+
"id": "9f6e6ef0",
|
29
|
+
"metadata": {},
|
30
|
+
"outputs": [],
|
31
|
+
"source": [
|
32
|
+
"# (REQUIRED) Create a new task. For Agentic agents, you must create a task for messages to be associated with.\n",
|
33
|
+
"\n",
|
34
|
+
"from typing import cast\n",
|
35
|
+
"import uuid\n",
|
36
|
+
"\n",
|
37
|
+
"from agentex.types import Task\n",
|
38
|
+
"\n",
|
39
|
+
"TASK_ID = str(uuid.uuid4())[:8]\n",
|
40
|
+
"\n",
|
41
|
+
"rpc_response = client.agents.rpc_by_name(\n",
|
42
|
+
" agent_name=AGENT_NAME,\n",
|
43
|
+
" method=\"task/create\",\n",
|
44
|
+
" params={\n",
|
45
|
+
" \"name\": f\"{TASK_ID}-task\",\n",
|
46
|
+
" \"params\": {}\n",
|
47
|
+
" }\n",
|
48
|
+
")\n",
|
49
|
+
"\n",
|
50
|
+
"task = cast(Task, rpc_response.result)\n",
|
51
|
+
"print(task)"
|
52
|
+
]
|
53
|
+
},
|
54
|
+
{
|
55
|
+
"cell_type": "code",
|
56
|
+
"execution_count": null,
|
57
|
+
"id": "b03b0d37",
|
58
|
+
"metadata": {},
|
59
|
+
"outputs": [],
|
60
|
+
"source": [
|
61
|
+
"# Test non streaming response\n",
|
62
|
+
"from typing import cast\n",
|
63
|
+
"from agentex.types import Event\n",
|
64
|
+
"\n",
|
65
|
+
"# The response is expected to be a list of TaskMessage objects, which is a union of the following types:\n",
|
66
|
+
"# - TextContent: A message with just text content \n",
|
67
|
+
"# - DataContent: A message with JSON-serializable data content\n",
|
68
|
+
"# - ToolRequestContent: A message with a tool request, which contains a JSON-serializable request to call a tool\n",
|
69
|
+
"# - ToolResponseContent: A message with a tool response, which contains response object from a tool call in its content\n",
|
70
|
+
"\n",
|
71
|
+
"# When processing the message/send response, if you are expecting more than TextContent, such as DataContent, ToolRequestContent, or ToolResponseContent, you can process them as well\n",
|
72
|
+
"\n",
|
73
|
+
"rpc_response = client.agents.rpc_by_name(\n",
|
74
|
+
" agent_name=AGENT_NAME,\n",
|
75
|
+
" method=\"event/send\",\n",
|
76
|
+
" params={\n",
|
77
|
+
" \"content\": {\"type\": \"text\", \"author\": \"user\", \"content\": \"Hello what can you do?\"},\n",
|
78
|
+
" \"task_id\": task.id,\n",
|
79
|
+
" }\n",
|
80
|
+
")\n",
|
81
|
+
"\n",
|
82
|
+
"event = cast(Event, rpc_response.result)\n",
|
83
|
+
"print(event)"
|
84
|
+
]
|
85
|
+
},
|
86
|
+
{
|
87
|
+
"cell_type": "code",
|
88
|
+
"execution_count": null,
|
89
|
+
"id": "a6927cc0",
|
90
|
+
"metadata": {},
|
91
|
+
"outputs": [],
|
92
|
+
"source": [
|
93
|
+
"from agentex.lib.utils.dev_tools import subscribe_to_async_task_messages\n",
|
94
|
+
"\n",
|
95
|
+
"task_messages = subscribe_to_async_task_messages(\n",
|
96
|
+
" client=client,\n",
|
97
|
+
" task=task, \n",
|
98
|
+
" only_after_timestamp=event.created_at, \n",
|
99
|
+
" print_messages=True,\n",
|
100
|
+
" rich_print=True,\n",
|
101
|
+
" timeout=5,\n",
|
102
|
+
")"
|
103
|
+
]
|
104
|
+
}
|
105
|
+
],
|
106
|
+
"metadata": {
|
107
|
+
"kernelspec": {
|
108
|
+
"display_name": ".venv",
|
109
|
+
"language": "python",
|
110
|
+
"name": "python3"
|
111
|
+
},
|
112
|
+
"language_info": {
|
113
|
+
"codemirror_mode": {
|
114
|
+
"name": "ipython",
|
115
|
+
"version": 3
|
116
|
+
},
|
117
|
+
"file_extension": ".py",
|
118
|
+
"mimetype": "text/x-python",
|
119
|
+
"name": "python",
|
120
|
+
"nbconvert_exporter": "python",
|
121
|
+
"pygments_lexer": "ipython3",
|
122
|
+
"version": "3.12.9"
|
123
|
+
}
|
124
|
+
},
|
125
|
+
"nbformat": 4,
|
126
|
+
"nbformat_minor": 5
|
127
|
+
}
|
@@ -7,7 +7,7 @@ from agentex.lib.types.acp import CreateTaskParams, SendEventParams
|
|
7
7
|
from agentex.lib.core.temporal.workflows.workflow import BaseWorkflow
|
8
8
|
from agentex.lib.core.temporal.types.workflow import SignalName
|
9
9
|
from agentex.lib.utils.logging import make_logger
|
10
|
-
from agentex.types.
|
10
|
+
from agentex.types.text_content import TextContent
|
11
11
|
from agentex.lib.environment_variables import EnvironmentVariables
|
12
12
|
|
13
13
|
environment_variables = EnvironmentVariables.refresh()
|
File without changes
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import base64
|
2
|
+
import json
|
3
|
+
|
4
|
+
from agentex.lib.sdk.config.agent_manifest import AgentManifest
|
5
|
+
|
6
|
+
|
7
|
+
# Base 64 encode principal dictionary
|
8
|
+
def _encode_principal_context(manifest: AgentManifest):
|
9
|
+
if manifest.auth is None:
|
10
|
+
return None
|
11
|
+
|
12
|
+
principal = manifest.auth.principal
|
13
|
+
if principal is None:
|
14
|
+
return None
|
15
|
+
|
16
|
+
json_str = json.dumps(principal, separators=(',', ':'))
|
17
|
+
encoded_bytes = base64.b64encode(json_str.encode('utf-8'))
|
18
|
+
return encoded_bytes.decode('utf-8')
|
@@ -7,13 +7,13 @@ from typing import Annotated, Any
|
|
7
7
|
import redis.asyncio as redis
|
8
8
|
from fastapi import Depends
|
9
9
|
|
10
|
-
from agentex.lib.core.adapters.streams.port import
|
10
|
+
from agentex.lib.core.adapters.streams.port import StreamRepository
|
11
11
|
from agentex.lib.utils.logging import make_logger
|
12
12
|
|
13
13
|
logger = make_logger(__name__)
|
14
14
|
|
15
15
|
|
16
|
-
class
|
16
|
+
class RedisStreamRepository(StreamRepository):
|
17
17
|
"""
|
18
18
|
A simplified Redis implementation of the EventStreamRepository interface.
|
19
19
|
Optimized for text/JSON streaming with SSE.
|
@@ -123,6 +123,6 @@ class RedisEventStreamRepository(EventStreamRepository):
|
|
123
123
|
raise
|
124
124
|
|
125
125
|
|
126
|
-
|
127
|
-
|
126
|
+
DRedisStreamRepository = Annotated[
|
127
|
+
RedisStreamRepository | None, Depends(RedisStreamRepository)
|
128
128
|
]
|
@@ -2,7 +2,7 @@ import json
|
|
2
2
|
from typing import Literal, cast
|
3
3
|
|
4
4
|
from agentex import AsyncAgentex
|
5
|
-
from agentex.lib.core.adapters.streams.port import
|
5
|
+
from agentex.lib.core.adapters.streams.port import StreamRepository
|
6
6
|
from agentex.lib.types.task_message_updates import (
|
7
7
|
TaskMessageDelta,
|
8
8
|
TaskMessageUpdate,
|
@@ -22,7 +22,6 @@ from agentex.types.task_message import (
|
|
22
22
|
TaskMessage,
|
23
23
|
TaskMessageContent,
|
24
24
|
)
|
25
|
-
from agentex.types.task_message_content_param import TaskMessageContentParam
|
26
25
|
from agentex.types.text_content import TextContent
|
27
26
|
from agentex.types.tool_request_content import ToolRequestContent
|
28
27
|
from agentex.types.tool_response_content import ToolResponseContent
|
@@ -221,7 +220,7 @@ class StreamingService:
|
|
221
220
|
def __init__(
|
222
221
|
self,
|
223
222
|
agentex_client: AsyncAgentex,
|
224
|
-
stream_repository:
|
223
|
+
stream_repository: StreamRepository,
|
225
224
|
):
|
226
225
|
self._agentex_client = agentex_client
|
227
226
|
self._stream_repository = stream_repository
|
@@ -2,7 +2,7 @@ from scale_gp import SGPClient, SGPClientError
|
|
2
2
|
|
3
3
|
from agentex import AsyncAgentex
|
4
4
|
from agentex.lib.core.adapters.llm.adapter_litellm import LiteLLMGateway
|
5
|
-
from agentex.lib.core.adapters.streams.adapter_redis import
|
5
|
+
from agentex.lib.core.adapters.streams.adapter_redis import RedisStreamRepository
|
6
6
|
from agentex.lib.core.services.adk.acp.acp import ACPService
|
7
7
|
from agentex.lib.core.services.adk.agent_task_tracker import AgentTaskTrackerService
|
8
8
|
from agentex.lib.core.services.adk.events import EventsService
|
@@ -57,7 +57,7 @@ def get_all_activities(sgp_client=None):
|
|
57
57
|
sgp_client = None
|
58
58
|
|
59
59
|
llm_gateway = LiteLLMGateway()
|
60
|
-
stream_repository =
|
60
|
+
stream_repository = RedisStreamRepository()
|
61
61
|
agentex_client = AsyncAgentex()
|
62
62
|
tracer = AsyncTracer(agentex_client)
|
63
63
|
|
@@ -24,9 +24,11 @@ class EnvVarKeys(str, Enum):
|
|
24
24
|
ACP_URL = "ACP_URL"
|
25
25
|
ACP_PORT = "ACP_PORT"
|
26
26
|
ACP_TYPE = "ACP_TYPE"
|
27
|
-
# Workflow
|
27
|
+
# Workflow Configuration
|
28
28
|
WORKFLOW_NAME = "WORKFLOW_NAME"
|
29
29
|
WORKFLOW_TASK_QUEUE = "WORKFLOW_TASK_QUEUE"
|
30
|
+
# Auth Configuration
|
31
|
+
AUTH_PRINCIPAL_B64 = "AUTH_PRINCIPAL_B64"
|
30
32
|
|
31
33
|
|
32
34
|
class Environment(str, Enum):
|
@@ -54,6 +56,7 @@ class EnvironmentVariables(BaseModel):
|
|
54
56
|
# Workflow Configuration
|
55
57
|
WORKFLOW_TASK_QUEUE: str | None = None
|
56
58
|
WORKFLOW_NAME: str | None = None
|
59
|
+
AUTH_PRINCIPAL_B64: str | None = None
|
57
60
|
|
58
61
|
@classmethod
|
59
62
|
def refresh(cls) -> EnvironmentVariables | None:
|
@@ -15,7 +15,7 @@ from pydantic import Field
|
|
15
15
|
|
16
16
|
from agentex.lib.sdk.config.agent_config import AgentConfig
|
17
17
|
from agentex.lib.sdk.config.build_config import BuildConfig
|
18
|
-
from agentex.lib.sdk.config.deployment_config import DeploymentConfig
|
18
|
+
from agentex.lib.sdk.config.deployment_config import DeploymentConfig, AuthenticationConfig
|
19
19
|
from agentex.lib.sdk.config.local_development_config import LocalDevelopmentConfig
|
20
20
|
from agentex.lib.utils.logging import make_logger
|
21
21
|
from agentex.lib.utils.model_utils import BaseModel
|
@@ -36,6 +36,7 @@ class AgentManifest(BaseModel):
|
|
36
36
|
deployment: DeploymentConfig | None = Field(
|
37
37
|
default=None, description="Deployment configuration for the agent"
|
38
38
|
)
|
39
|
+
auth: AuthenticationConfig | None = Field(default=None, description="Authentication configuration")
|
39
40
|
|
40
41
|
def context_manager(self, build_context_root: Path) -> BuildContextManager:
|
41
42
|
"""
|
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import Any
|
1
|
+
from typing import Any, Dict
|
2
2
|
|
3
3
|
from pydantic import Field
|
4
4
|
|
@@ -90,6 +90,10 @@ class ClusterConfig(BaseModel):
|
|
90
90
|
)
|
91
91
|
|
92
92
|
|
93
|
+
class AuthenticationConfig(BaseModel):
|
94
|
+
principal: Dict[str, Any] = Field(description="Principal used for authorization on registration")
|
95
|
+
|
96
|
+
|
93
97
|
class InjectedImagePullSecretValues(BaseModel):
|
94
98
|
"""Values for image pull secrets"""
|
95
99
|
|
@@ -1,5 +1,7 @@
|
|
1
1
|
import asyncio
|
2
|
+
import base64
|
2
3
|
import inspect
|
4
|
+
import json
|
3
5
|
from collections.abc import AsyncGenerator, Awaitable, Callable
|
4
6
|
from contextlib import asynccontextmanager
|
5
7
|
from typing import Any
|
@@ -341,6 +343,16 @@ class BaseACPServer(FastAPI):
|
|
341
343
|
"""Start the Uvicorn server for async handlers."""
|
342
344
|
uvicorn.run(self, host=host, port=port, **kwargs)
|
343
345
|
|
346
|
+
def _get_auth_principal(self, env_vars: EnvironmentVariables):
|
347
|
+
if not env_vars.AUTH_PRINCIPAL_B64:
|
348
|
+
return None
|
349
|
+
|
350
|
+
try:
|
351
|
+
decoded_str = base64.b64decode(env_vars.AUTH_PRINCIPAL_B64).decode('utf-8')
|
352
|
+
return json.loads(decoded_str)
|
353
|
+
except Exception:
|
354
|
+
return None
|
355
|
+
|
344
356
|
async def _register_agent(self, env_vars: EnvironmentVariables):
|
345
357
|
"""Register this agent with the Agentex server"""
|
346
358
|
# Build the agent's own URL
|
@@ -350,12 +362,14 @@ class BaseACPServer(FastAPI):
|
|
350
362
|
env_vars.AGENT_DESCRIPTION
|
351
363
|
or f"Generic description for agent: {env_vars.AGENT_NAME}"
|
352
364
|
)
|
365
|
+
|
353
366
|
# Prepare registration data
|
354
367
|
registration_data = {
|
355
368
|
"name": env_vars.AGENT_NAME,
|
356
369
|
"description": description,
|
357
370
|
"acp_url": full_acp_url,
|
358
371
|
"acp_type": env_vars.ACP_TYPE,
|
372
|
+
"principal_context": self._get_auth_principal(env_vars)
|
359
373
|
}
|
360
374
|
|
361
375
|
if env_vars.AGENT_ID:
|