workflow-exec-engine 0.0.3__tar.gz

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.
Files changed (42) hide show
  1. workflow_exec_engine-0.0.3/LICENSE +17 -0
  2. workflow_exec_engine-0.0.3/MANIFEST.in +4 -0
  3. workflow_exec_engine-0.0.3/PKG-INFO +309 -0
  4. workflow_exec_engine-0.0.3/README.md +279 -0
  5. workflow_exec_engine-0.0.3/README_en.md +279 -0
  6. workflow_exec_engine-0.0.3/examples/execute_psop_demo.py +72 -0
  7. workflow_exec_engine-0.0.3/examples/quickstart.py +106 -0
  8. workflow_exec_engine-0.0.3/pyproject.toml +43 -0
  9. workflow_exec_engine-0.0.3/requirements.txt +6 -0
  10. workflow_exec_engine-0.0.3/setup.cfg +4 -0
  11. workflow_exec_engine-0.0.3/workflow_engine/__init__.py +95 -0
  12. workflow_exec_engine-0.0.3/workflow_engine/client/__init__.py +47 -0
  13. workflow_exec_engine-0.0.3/workflow_engine/client/a2a_transport.py +560 -0
  14. workflow_exec_engine-0.0.3/workflow_engine/client/agentcard_normalizer.py +106 -0
  15. workflow_exec_engine-0.0.3/workflow_engine/client/auth_manager.py +127 -0
  16. workflow_exec_engine-0.0.3/workflow_engine/client/auth_provider.py +47 -0
  17. workflow_exec_engine-0.0.3/workflow_engine/client/credential_crypto.py +102 -0
  18. workflow_exec_engine-0.0.3/workflow_engine/client/credential_service.py +229 -0
  19. workflow_exec_engine-0.0.3/workflow_engine/client/engine_client.py +374 -0
  20. workflow_exec_engine-0.0.3/workflow_engine/client/env_file_loader.py +68 -0
  21. workflow_exec_engine-0.0.3/workflow_engine/client/extension_handlers.py +203 -0
  22. workflow_exec_engine-0.0.3/workflow_engine/client/extension_interceptor.py +76 -0
  23. workflow_exec_engine-0.0.3/workflow_engine/client/extension_sender.py +203 -0
  24. workflow_exec_engine-0.0.3/workflow_engine/client/extensions.py +43 -0
  25. workflow_exec_engine-0.0.3/workflow_engine/client/protocol_logger.py +78 -0
  26. workflow_exec_engine-0.0.3/workflow_engine/client/sse_normalization.py +87 -0
  27. workflow_exec_engine-0.0.3/workflow_engine/client/ssl_context.py +84 -0
  28. workflow_exec_engine-0.0.3/workflow_engine/client/stub_engine_client.py +68 -0
  29. workflow_exec_engine-0.0.3/workflow_engine/control/__init__.py +26 -0
  30. workflow_exec_engine-0.0.3/workflow_engine/control/control_points.py +223 -0
  31. workflow_exec_engine-0.0.3/workflow_engine/core/__init__.py +34 -0
  32. workflow_exec_engine-0.0.3/workflow_engine/core/context_builder.py +101 -0
  33. workflow_exec_engine-0.0.3/workflow_engine/core/executor.py +278 -0
  34. workflow_exec_engine-0.0.3/workflow_engine/core/models.py +184 -0
  35. workflow_exec_engine-0.0.3/workflow_engine/registry/__init__.py +21 -0
  36. workflow_exec_engine-0.0.3/workflow_engine/registry/registry_client.py +177 -0
  37. workflow_exec_engine-0.0.3/workflow_engine/runner.py +247 -0
  38. workflow_exec_engine-0.0.3/workflow_exec_engine.egg-info/PKG-INFO +309 -0
  39. workflow_exec_engine-0.0.3/workflow_exec_engine.egg-info/SOURCES.txt +40 -0
  40. workflow_exec_engine-0.0.3/workflow_exec_engine.egg-info/dependency_links.txt +1 -0
  41. workflow_exec_engine-0.0.3/workflow_exec_engine.egg-info/requires.txt +7 -0
  42. workflow_exec_engine-0.0.3/workflow_exec_engine.egg-info/top_level.txt +1 -0
@@ -0,0 +1,17 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ Copyright 2026 Huawei Technologies Co., Ltd.
6
+
7
+ Licensed under the Apache License, Version 2.0 (the "License");
8
+ you may not use this file except in compliance with the License.
9
+ You may obtain a copy of the License at
10
+
11
+ http://www.apache.org/licenses/LICENSE-2.0
12
+
13
+ Unless required by applicable law or agreed to in writing, software
14
+ distributed under the License is distributed on an "AS IS" BASIS,
15
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ See the License for the specific language governing permissions and
17
+ limitations under the License.
@@ -0,0 +1,4 @@
1
+ include README.md
2
+ include README_en.md
3
+ include requirements.txt
4
+ recursive-include examples *.py
@@ -0,0 +1,309 @@
1
+ Metadata-Version: 2.4
2
+ Name: workflow-exec-engine
3
+ Version: 0.0.3
4
+ Summary: Standalone workflow execution SDK for A2A-T multi-agent orchestration
5
+ Author-email: A2A SDK Team <ivo.zhou@huawei.com>
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/Zhoujie628/workflow-exec-engine
8
+ Project-URL: Documentation, https://github.com/Zhoujie628/workflow-exec-engine#readme
9
+ Project-URL: Repository, https://github.com/Zhoujie628/workflow-exec-engine
10
+ Keywords: a2a,agent,orchestration,workflow,sdk
11
+ Classifier: Development Status :: 2 - Pre-Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Software Development :: Libraries
19
+ Requires-Python: >=3.12
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: a2a-sdk>=1.0.0
23
+ Requires-Dist: a2a-t-sdk>=1.0.0
24
+ Requires-Dist: httpx>=0.27.0
25
+ Requires-Dist: loguru>=0.7.0
26
+ Requires-Dist: protobuf>=4.25.0
27
+ Requires-Dist: packaging>=23.0
28
+ Requires-Dist: cryptography>=42.0.0
29
+ Dynamic: license-file
30
+
31
+ # workflow-engine
32
+
33
+ 独立工作流执行 SDK,支持宿主 Agent 执行编排中心工作流(PSOP),同时保留对 A2A 通信、A2A-T 扩展与路由决策的完全控制权。SDK 自包含,不依赖编排中心任何代码。
34
+
35
+ > 完整设计参见 [DESIGN.md](DESIGN.md)。本文档面向集成者,快速上手与接口说明。
36
+
37
+ ## 设计原则
38
+
39
+ | SDK 提供(协议机制) | 用户控制(业务决策) |
40
+ |---|---|
41
+ | A2A 消息发送、流式、SSE 归一化 | 何时 / 是否发送任务 |
42
+ | Agent 认证(Bearer、自定义 Header,基于 AgentCard) | 凭据配置 |
43
+ | A2A-T 扩展(Task-T、Negotiation-T、Authorization-T、Notification-T) | 授权审批、通知处理 |
44
+ | DAG 遍历、上下文组装、状态管理 | 分支路由决策 |
45
+ | 事件追踪 | 事件处理方式 |
46
+
47
+ ## 架构
48
+
49
+ 共享传输层 + 两个门面,职责单一:
50
+
51
+ ```
52
+ A2ATransport(共享通信层:httpx + 认证 + AgentCard 映射 + SSE 消费)
53
+ ├── WorkflowEngineClient(工作流发送门面:Task-T 生成、Negotiation-T 自动循环、事件回调、ControlPoint 装配)
54
+ └── ExtensionSender(一次性预置门面:Authorization-T / Notification-T 发送)
55
+ ```
56
+
57
+ 决策层接口:
58
+
59
+ - **ControlPoint** — 流程决策(`on_task` / `on_self_task` / `on_route` / `on_negotiation`)
60
+
61
+ Authorization-T 和 Notification-T 是预置操作,在工作流启动前通过 `ExtensionSender` 单向下发,不在工作流执行中回调。
62
+
63
+ ```mermaid
64
+ flowchart TB
65
+ subgraph User["用户(宿主 Agent)"]
66
+ AC["AgentCards<br/>(注册中心或自定义来源)"]
67
+ CP["ControlPoint<br/>流程决策"]
68
+ end
69
+ subgraph SDK["SDK(自包含)"]
70
+ TR["A2ATransport<br/>共享通信层"]
71
+ WEC["WorkflowEngineClient<br/>工作流发送"]
72
+ ES["ExtensionSender<br/>一次性预置"]
73
+ WE["WorkflowExecutor<br/>DAG 遍历"]
74
+ end
75
+ subgraph Agents["远端 Agents"]
76
+ A1["Agent A"]
77
+ A2["Agent B"]
78
+ end
79
+ AC --> TR
80
+ TR --> WEC
81
+ TR --> ES
82
+ WEC -->|send_message| A1
83
+ WEC -->|send_message| A2
84
+ ES -->|预置发送| A1
85
+ WE -->|on_task/on_route| CP
86
+ WEC -->|on_negotiation| CP
87
+ ```
88
+
89
+ ## 快速开始
90
+
91
+ ```python
92
+ import asyncio
93
+ from workflow_engine import (
94
+ execute_psop, ControlPoint, RouteDecision,
95
+ TaskResponse, RegistryClient, load_psop,
96
+ )
97
+
98
+
99
+ class MyControlPoint(ControlPoint):
100
+ async def on_task(self, request, engine_client):
101
+ # SDK 已组装完整消息(上下文 + 任务 + 语言提示),直接发送
102
+ result = await engine_client.send_message(
103
+ request.agent_name, request.message
104
+ )
105
+ return TaskResponse(success=bool(result.text), output=result.text)
106
+
107
+ async def on_route(self, step_name, results, conditions):
108
+ # conditions: List[JumpCondition],每个含 .step 与 .condition
109
+ # 用你的 LLM 或业务逻辑选一个分支
110
+ return RouteDecision(next_step=conditions[0].step)
111
+
112
+
113
+ async def main():
114
+ # 1. 获取 AgentCards(注册中心或自定义来源)
115
+ registry = RegistryClient(url="https://127.0.0.1:5000", ssl_verify=False)
116
+ agent_cards = await registry.fetch_agent_cards()
117
+
118
+ # 2. 加载 PSOP 工作流
119
+ workflow = await load_psop(
120
+ base_url="https://127.0.0.1:5001",
121
+ psop_id="your-psop-id",
122
+ ssl_verify=False,
123
+ )
124
+
125
+ # 3. 执行:execute_psop 内部构建 A2ATransport + WorkflowEngineClient
126
+ async for event in execute_psop(
127
+ psop=workflow,
128
+ agent_cards=agent_cards,
129
+ control_point=MyControlPoint(),
130
+ a2at_env_path=".env",
131
+ credentials_config="agent_credentials.json",
132
+ runtime_intent="诊断 SPN 跨市故障",
133
+ ssl_verify=False,
134
+ ):
135
+ print(f"[{event['type']}] {event['data']}")
136
+
137
+
138
+ if __name__ == "__main__":
139
+ asyncio.run(main())
140
+ ```
141
+
142
+ ## 分层入口
143
+
144
+ | 层 | 入口 | 处理 | 你提供 |
145
+ |---|---|---|---|
146
+ | 2(高) | `execute_psop()` | 事件流、生命周期、取消、onFinish | ControlPoint + AgentCards + 配置 |
147
+ | 1(中) | `WorkflowExecutor` | DAG 遍历、上下文组装、调度 | ControlPoint + WorkflowEngineClient + Workflow |
148
+ | 0(低) | `A2ATransport` + 两个门面 | A2A 发送、认证、扩展、SSE | AgentCards + 配置 |
149
+
150
+ 大多数集成使用第 2 层。需要手动控制时使用第 1 层。仅做一次性预置发送时直接使用 `ExtensionSender`。
151
+
152
+ ## 用户实现的接口
153
+
154
+ ### ControlPoint(流程决策)
155
+
156
+ | 方法 | 必需 | 调用时机 | 决定 |
157
+ |---|---|---|---|
158
+ | `on_task(request, engine_client)` | 是 | 步骤需向 Agent 发送任务 | 是否 / 如何发送 |
159
+ | `on_self_task(request)` | 否(默认回显) | SELF_LOOP 步骤 | 本地处理结果 |
160
+ | `on_route(step_name, results, conditions)` | 是 | 步骤有条件分支 | 走哪个分支 |
161
+ | `on_negotiation(agent_name, text, result)` | 否(默认通用澄清) | Agent 返回 INPUT_REQUIRED | 补充澄清文本 |
162
+
163
+ ## A2ATransport + 门面(第 0 层)
164
+
165
+ ```python
166
+ from workflow_engine import A2ATransport, WorkflowEngineClient, ExtensionSender
167
+
168
+ transport = A2ATransport(
169
+ agent_cards=agent_cards,
170
+ a2at_env_path=".env",
171
+ credentials_config="agent_credentials.json",
172
+ ssl_verify=False,
173
+ )
174
+
175
+ # 工作流发送门面
176
+ engine_client = WorkflowEngineClient(transport)
177
+
178
+ # 一次性预置门面(工作流开始前)
179
+ sender = ExtensionSender(transport)
180
+ auth_result = await sender.send_authorization("agent_a", "授权诊断操作", "诊断 SPN 跨市故障")
181
+ notif_result = await sender.send_notification("agent_a", "订阅恢复结果通知", "诊断 SPN 跨市故障")
182
+ ```
183
+
184
+ 两个门面共享同一个 transport,不重复 wire 代码。
185
+
186
+ **前置操作的回调**:Authorization-T 和 Notification-T 是工作流开始前的一次性操作,通过 `ExtensionSender` 发送。发送结果直接通过返回的 `SendMessageResult` 获取,无需额外的回调接口。
187
+
188
+ ## A2A-T 扩展
189
+
190
+ | 扩展 | 归属 | 说明 |
191
+ |---|---|---|
192
+ | Task-T | 工作流链路 | 发送时由 SDK 生成结构化任务提示并注入 `metadata["...Task-T/v1"]` |
193
+ | Negotiation-T | 工作流链路 | 接收时从 `metadata["...NEGOTIATION-T"]` 提取协商上下文,驱动自动循环 |
194
+ | Authorization-T | 一次性预置 | 工作流开始前通过 `ExtensionSender` 发送,`instruction` → `parts[].text`,`natural_language_input` → SDK 生成结构化策略 → `metadata["...Authorization-T/v1"]` |
195
+ | Notification-T | 一次性预置 | 工作流开始前通过 `ExtensionSender` 发送,`instruction` → `parts[].text`,`natural_language_input` → SDK 生成结构化订阅 → `metadata["...Notification-T/v1"]` |
196
+
197
+ `ExtensionRegistry` 自动注册 Task-T 与 Negotiation-T(工作流内处理器);Authorization-T / Notification-T 是预置操作,不自动注册,其 handler 类保留供手动注册处理 Agent 内联推送的数据。
198
+
199
+ ## 智能体认证配置
200
+
201
+ 当 AgentCard 声明 `securitySchemes` 与 `securityRequirements` 时,SDK 自动通过登录接口获取 token 并将认证头附加到出站请求。创建 JSON 文件:
202
+
203
+ ```json
204
+ {
205
+ "agent_a": {
206
+ "bearerAuth": {
207
+ "login_url": "https://127.0.0.1:8080/auth/login",
208
+ "method": "POST",
209
+ "content_type": "application/json",
210
+ "request_fields": { "username": "user", "password": "pass" },
211
+ "token_field": "access_token",
212
+ "token_ttl": 3600,
213
+ "auth_header": "Authorization",
214
+ "auth_header_prefix": "Bearer "
215
+ }
216
+ }
217
+ }
218
+ ```
219
+
220
+ | 字段 | 必填 | 默认 | 说明 |
221
+ |---|---|---|---|
222
+ | login_url | 是 | - | 获取 token 的 URL |
223
+ | method | 否 | POST | HTTP 方法 |
224
+ | content_type | 否 | application/json | 请求内容类型 |
225
+ | request_fields | 否 | - | 请求体字段(覆盖 username/password) |
226
+ | token_field | 否 | accessSession | 响应中提取 token 的路径(点分隔) |
227
+ | token_ttl | 否 | 3600 | token 缓存时长(秒) |
228
+ | auth_header | 否 | Authorization | 自定义认证头名 |
229
+ | auth_header_prefix | 否 | 空 | token 前缀(如 Bearer) |
230
+ | accept_header | 否 | - | 自定义 Accept 头 |
231
+
232
+ 智能体名称须与 AgentCard 的 `name` 一致;认证方案名须与 `securitySchemes` 键一致。也可直接传 dict:`credentials_config=dict`。参见 `examples/agent_credentials.example.json`。
233
+
234
+ **密码加密:**
235
+
236
+ `request_fields` 中的密码字段支持 `enc:` 前缀加密格式 `enc:<base64-iv>:<base64-ciphertext>`,算法为 AES-256-GCM。SDK 运行时从 `A2AT_CRED_KEY` 环境变量读取密钥自动解密。
237
+
238
+ ```bash
239
+ # 1. 生成 32 字节密钥 (仅首次)
240
+ python -c "import secrets; print(secrets.token_hex(32))"
241
+
242
+ # 2. 设置密钥环境变量
243
+ export A2AT_CRED_KEY=a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2
244
+
245
+ # 3. 加密密码
246
+ python -c "from workflow_engine.client.credential_crypto import encrypt; print(encrypt('Admin@123'))"
247
+ # 输出: enc:xxxxxxxxxxxx:yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
248
+ ```
249
+
250
+ 将输出的 `enc:...` 值填入 credentials JSON 的密码字段即可。
251
+
252
+ ### 自定义 AuthProvider
253
+
254
+ 对于非标准认证(企业 SSO、外部身份提供商、AgentCard 无 `securitySchemes` 但仍需认证),实现 `AuthProvider` ABC:
255
+
256
+ ```python
257
+ from workflow_engine import AuthProvider
258
+
259
+ class SsoAuthProvider(AuthProvider):
260
+ def apply_auth(self, agent_name: str, agent_card, headers: dict) -> None:
261
+ token = sso_client.get_access_token(agent_name)
262
+ headers["Authorization"] = f"Bearer {token}"
263
+
264
+ transport = A2ATransport(
265
+ agent_cards=agent_cards,
266
+ auth_provider=SsoAuthProvider(),
267
+ )
268
+ ```
269
+
270
+ 两种方式可组合使用:`AuthProvider` 先执行,credentials 认证后执行,各自向请求头注入认证信息。
271
+
272
+ ## 文件结构
273
+
274
+ ```
275
+ workflow-exec-engine/
276
+ ├── README.md # 本文档
277
+ ├── README_en.md # English
278
+ ├── DESIGN.md # 设计文档
279
+ ├── DEVELOPER_GUIDE.md # 开发者指南
280
+ ├── pyproject.toml
281
+ ├── examples/
282
+ │ ├── quickstart.py
283
+ │ └── execute_psop_demo.py
284
+ └── workflow_engine/
285
+ ├── __init__.py # 公共 API 导出
286
+ ├── runner.py # execute_psop 高层运行器
287
+ ├── core/ # 核心执行
288
+ │ ├── models.py # 数据模型
289
+ │ ├── context_builder.py
290
+ │ └── executor.py # WorkflowExecutor DAG 遍历
291
+ ├── client/ # 通信层
292
+ │ ├── a2a_transport.py # A2ATransport 共享通信层
293
+ │ ├── engine_client.py # WorkflowEngineClient 工作流门面
294
+ │ ├── extension_sender.py # ExtensionSender 一次性门面
295
+ │ ├── extension_handlers.py
296
+ │ ├── extensions.py # A2ATExtension 枚举
297
+ │ ├── auth_manager.py
298
+ │ ├── credential_service.py
299
+ │ ├── ssl_context.py
300
+ │ └── sse_normalization.py
301
+ ├── control/ # 决策接口
302
+ │ └── control_points.py # ControlPoint + EventType
303
+ └── registry/ # 注册中心集成(可选)
304
+ └── registry_client.py
305
+ ```
306
+
307
+ ## 许可证
308
+
309
+ Apache License 2.0
@@ -0,0 +1,279 @@
1
+ # workflow-engine
2
+
3
+ 独立工作流执行 SDK,支持宿主 Agent 执行编排中心工作流(PSOP),同时保留对 A2A 通信、A2A-T 扩展与路由决策的完全控制权。SDK 自包含,不依赖编排中心任何代码。
4
+
5
+ > 完整设计参见 [DESIGN.md](DESIGN.md)。本文档面向集成者,快速上手与接口说明。
6
+
7
+ ## 设计原则
8
+
9
+ | SDK 提供(协议机制) | 用户控制(业务决策) |
10
+ |---|---|
11
+ | A2A 消息发送、流式、SSE 归一化 | 何时 / 是否发送任务 |
12
+ | Agent 认证(Bearer、自定义 Header,基于 AgentCard) | 凭据配置 |
13
+ | A2A-T 扩展(Task-T、Negotiation-T、Authorization-T、Notification-T) | 授权审批、通知处理 |
14
+ | DAG 遍历、上下文组装、状态管理 | 分支路由决策 |
15
+ | 事件追踪 | 事件处理方式 |
16
+
17
+ ## 架构
18
+
19
+ 共享传输层 + 两个门面,职责单一:
20
+
21
+ ```
22
+ A2ATransport(共享通信层:httpx + 认证 + AgentCard 映射 + SSE 消费)
23
+ ├── WorkflowEngineClient(工作流发送门面:Task-T 生成、Negotiation-T 自动循环、事件回调、ControlPoint 装配)
24
+ └── ExtensionSender(一次性预置门面:Authorization-T / Notification-T 发送)
25
+ ```
26
+
27
+ 决策层接口:
28
+
29
+ - **ControlPoint** — 流程决策(`on_task` / `on_self_task` / `on_route` / `on_negotiation`)
30
+
31
+ Authorization-T 和 Notification-T 是预置操作,在工作流启动前通过 `ExtensionSender` 单向下发,不在工作流执行中回调。
32
+
33
+ ```mermaid
34
+ flowchart TB
35
+ subgraph User["用户(宿主 Agent)"]
36
+ AC["AgentCards<br/>(注册中心或自定义来源)"]
37
+ CP["ControlPoint<br/>流程决策"]
38
+ end
39
+ subgraph SDK["SDK(自包含)"]
40
+ TR["A2ATransport<br/>共享通信层"]
41
+ WEC["WorkflowEngineClient<br/>工作流发送"]
42
+ ES["ExtensionSender<br/>一次性预置"]
43
+ WE["WorkflowExecutor<br/>DAG 遍历"]
44
+ end
45
+ subgraph Agents["远端 Agents"]
46
+ A1["Agent A"]
47
+ A2["Agent B"]
48
+ end
49
+ AC --> TR
50
+ TR --> WEC
51
+ TR --> ES
52
+ WEC -->|send_message| A1
53
+ WEC -->|send_message| A2
54
+ ES -->|预置发送| A1
55
+ WE -->|on_task/on_route| CP
56
+ WEC -->|on_negotiation| CP
57
+ ```
58
+
59
+ ## 快速开始
60
+
61
+ ```python
62
+ import asyncio
63
+ from workflow_engine import (
64
+ execute_psop, ControlPoint, RouteDecision,
65
+ TaskResponse, RegistryClient, load_psop,
66
+ )
67
+
68
+
69
+ class MyControlPoint(ControlPoint):
70
+ async def on_task(self, request, engine_client):
71
+ # SDK 已组装完整消息(上下文 + 任务 + 语言提示),直接发送
72
+ result = await engine_client.send_message(
73
+ request.agent_name, request.message
74
+ )
75
+ return TaskResponse(success=bool(result.text), output=result.text)
76
+
77
+ async def on_route(self, step_name, results, conditions):
78
+ # conditions: List[JumpCondition],每个含 .step 与 .condition
79
+ # 用你的 LLM 或业务逻辑选一个分支
80
+ return RouteDecision(next_step=conditions[0].step)
81
+
82
+
83
+ async def main():
84
+ # 1. 获取 AgentCards(注册中心或自定义来源)
85
+ registry = RegistryClient(url="https://127.0.0.1:5000", ssl_verify=False)
86
+ agent_cards = await registry.fetch_agent_cards()
87
+
88
+ # 2. 加载 PSOP 工作流
89
+ workflow = await load_psop(
90
+ base_url="https://127.0.0.1:5001",
91
+ psop_id="your-psop-id",
92
+ ssl_verify=False,
93
+ )
94
+
95
+ # 3. 执行:execute_psop 内部构建 A2ATransport + WorkflowEngineClient
96
+ async for event in execute_psop(
97
+ psop=workflow,
98
+ agent_cards=agent_cards,
99
+ control_point=MyControlPoint(),
100
+ a2at_env_path=".env",
101
+ credentials_config="agent_credentials.json",
102
+ runtime_intent="诊断 SPN 跨市故障",
103
+ ssl_verify=False,
104
+ ):
105
+ print(f"[{event['type']}] {event['data']}")
106
+
107
+
108
+ if __name__ == "__main__":
109
+ asyncio.run(main())
110
+ ```
111
+
112
+ ## 分层入口
113
+
114
+ | 层 | 入口 | 处理 | 你提供 |
115
+ |---|---|---|---|
116
+ | 2(高) | `execute_psop()` | 事件流、生命周期、取消、onFinish | ControlPoint + AgentCards + 配置 |
117
+ | 1(中) | `WorkflowExecutor` | DAG 遍历、上下文组装、调度 | ControlPoint + WorkflowEngineClient + Workflow |
118
+ | 0(低) | `A2ATransport` + 两个门面 | A2A 发送、认证、扩展、SSE | AgentCards + 配置 |
119
+
120
+ 大多数集成使用第 2 层。需要手动控制时使用第 1 层。仅做一次性预置发送时直接使用 `ExtensionSender`。
121
+
122
+ ## 用户实现的接口
123
+
124
+ ### ControlPoint(流程决策)
125
+
126
+ | 方法 | 必需 | 调用时机 | 决定 |
127
+ |---|---|---|---|
128
+ | `on_task(request, engine_client)` | 是 | 步骤需向 Agent 发送任务 | 是否 / 如何发送 |
129
+ | `on_self_task(request)` | 否(默认回显) | SELF_LOOP 步骤 | 本地处理结果 |
130
+ | `on_route(step_name, results, conditions)` | 是 | 步骤有条件分支 | 走哪个分支 |
131
+ | `on_negotiation(agent_name, text, result)` | 否(默认通用澄清) | Agent 返回 INPUT_REQUIRED | 补充澄清文本 |
132
+
133
+ ## A2ATransport + 门面(第 0 层)
134
+
135
+ ```python
136
+ from workflow_engine import A2ATransport, WorkflowEngineClient, ExtensionSender
137
+
138
+ transport = A2ATransport(
139
+ agent_cards=agent_cards,
140
+ a2at_env_path=".env",
141
+ credentials_config="agent_credentials.json",
142
+ ssl_verify=False,
143
+ )
144
+
145
+ # 工作流发送门面
146
+ engine_client = WorkflowEngineClient(transport)
147
+
148
+ # 一次性预置门面(工作流开始前)
149
+ sender = ExtensionSender(transport)
150
+ auth_result = await sender.send_authorization("agent_a", "授权诊断操作", "诊断 SPN 跨市故障")
151
+ notif_result = await sender.send_notification("agent_a", "订阅恢复结果通知", "诊断 SPN 跨市故障")
152
+ ```
153
+
154
+ 两个门面共享同一个 transport,不重复 wire 代码。
155
+
156
+ **前置操作的回调**:Authorization-T 和 Notification-T 是工作流开始前的一次性操作,通过 `ExtensionSender` 发送。发送结果直接通过返回的 `SendMessageResult` 获取,无需额外的回调接口。
157
+
158
+ ## A2A-T 扩展
159
+
160
+ | 扩展 | 归属 | 说明 |
161
+ |---|---|---|
162
+ | Task-T | 工作流链路 | 发送时由 SDK 生成结构化任务提示并注入 `metadata["...Task-T/v1"]` |
163
+ | Negotiation-T | 工作流链路 | 接收时从 `metadata["...NEGOTIATION-T"]` 提取协商上下文,驱动自动循环 |
164
+ | Authorization-T | 一次性预置 | 工作流开始前通过 `ExtensionSender` 发送,`instruction` → `parts[].text`,`natural_language_input` → SDK 生成结构化策略 → `metadata["...Authorization-T/v1"]` |
165
+ | Notification-T | 一次性预置 | 工作流开始前通过 `ExtensionSender` 发送,`instruction` → `parts[].text`,`natural_language_input` → SDK 生成结构化订阅 → `metadata["...Notification-T/v1"]` |
166
+
167
+ `ExtensionRegistry` 自动注册 Task-T 与 Negotiation-T(工作流内处理器);Authorization-T / Notification-T 是预置操作,不自动注册,其 handler 类保留供手动注册处理 Agent 内联推送的数据。
168
+
169
+ ## 智能体认证配置
170
+
171
+ 当 AgentCard 声明 `securitySchemes` 与 `securityRequirements` 时,SDK 自动通过登录接口获取 token 并将认证头附加到出站请求。创建 JSON 文件:
172
+
173
+ ```json
174
+ {
175
+ "agent_a": {
176
+ "bearerAuth": {
177
+ "login_url": "https://127.0.0.1:8080/auth/login",
178
+ "method": "POST",
179
+ "content_type": "application/json",
180
+ "request_fields": { "username": "user", "password": "pass" },
181
+ "token_field": "access_token",
182
+ "token_ttl": 3600,
183
+ "auth_header": "Authorization",
184
+ "auth_header_prefix": "Bearer "
185
+ }
186
+ }
187
+ }
188
+ ```
189
+
190
+ | 字段 | 必填 | 默认 | 说明 |
191
+ |---|---|---|---|
192
+ | login_url | 是 | - | 获取 token 的 URL |
193
+ | method | 否 | POST | HTTP 方法 |
194
+ | content_type | 否 | application/json | 请求内容类型 |
195
+ | request_fields | 否 | - | 请求体字段(覆盖 username/password) |
196
+ | token_field | 否 | accessSession | 响应中提取 token 的路径(点分隔) |
197
+ | token_ttl | 否 | 3600 | token 缓存时长(秒) |
198
+ | auth_header | 否 | Authorization | 自定义认证头名 |
199
+ | auth_header_prefix | 否 | 空 | token 前缀(如 Bearer) |
200
+ | accept_header | 否 | - | 自定义 Accept 头 |
201
+
202
+ 智能体名称须与 AgentCard 的 `name` 一致;认证方案名须与 `securitySchemes` 键一致。也可直接传 dict:`credentials_config=dict`。参见 `examples/agent_credentials.example.json`。
203
+
204
+ **密码加密:**
205
+
206
+ `request_fields` 中的密码字段支持 `enc:` 前缀加密格式 `enc:<base64-iv>:<base64-ciphertext>`,算法为 AES-256-GCM。SDK 运行时从 `A2AT_CRED_KEY` 环境变量读取密钥自动解密。
207
+
208
+ ```bash
209
+ # 1. 生成 32 字节密钥 (仅首次)
210
+ python -c "import secrets; print(secrets.token_hex(32))"
211
+
212
+ # 2. 设置密钥环境变量
213
+ export A2AT_CRED_KEY=a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2
214
+
215
+ # 3. 加密密码
216
+ python -c "from workflow_engine.client.credential_crypto import encrypt; print(encrypt('Admin@123'))"
217
+ # 输出: enc:xxxxxxxxxxxx:yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
218
+ ```
219
+
220
+ 将输出的 `enc:...` 值填入 credentials JSON 的密码字段即可。
221
+
222
+ ### 自定义 AuthProvider
223
+
224
+ 对于非标准认证(企业 SSO、外部身份提供商、AgentCard 无 `securitySchemes` 但仍需认证),实现 `AuthProvider` ABC:
225
+
226
+ ```python
227
+ from workflow_engine import AuthProvider
228
+
229
+ class SsoAuthProvider(AuthProvider):
230
+ def apply_auth(self, agent_name: str, agent_card, headers: dict) -> None:
231
+ token = sso_client.get_access_token(agent_name)
232
+ headers["Authorization"] = f"Bearer {token}"
233
+
234
+ transport = A2ATransport(
235
+ agent_cards=agent_cards,
236
+ auth_provider=SsoAuthProvider(),
237
+ )
238
+ ```
239
+
240
+ 两种方式可组合使用:`AuthProvider` 先执行,credentials 认证后执行,各自向请求头注入认证信息。
241
+
242
+ ## 文件结构
243
+
244
+ ```
245
+ workflow-exec-engine/
246
+ ├── README.md # 本文档
247
+ ├── README_en.md # English
248
+ ├── DESIGN.md # 设计文档
249
+ ├── DEVELOPER_GUIDE.md # 开发者指南
250
+ ├── pyproject.toml
251
+ ├── examples/
252
+ │ ├── quickstart.py
253
+ │ └── execute_psop_demo.py
254
+ └── workflow_engine/
255
+ ├── __init__.py # 公共 API 导出
256
+ ├── runner.py # execute_psop 高层运行器
257
+ ├── core/ # 核心执行
258
+ │ ├── models.py # 数据模型
259
+ │ ├── context_builder.py
260
+ │ └── executor.py # WorkflowExecutor DAG 遍历
261
+ ├── client/ # 通信层
262
+ │ ├── a2a_transport.py # A2ATransport 共享通信层
263
+ │ ├── engine_client.py # WorkflowEngineClient 工作流门面
264
+ │ ├── extension_sender.py # ExtensionSender 一次性门面
265
+ │ ├── extension_handlers.py
266
+ │ ├── extensions.py # A2ATExtension 枚举
267
+ │ ├── auth_manager.py
268
+ │ ├── credential_service.py
269
+ │ ├── ssl_context.py
270
+ │ └── sse_normalization.py
271
+ ├── control/ # 决策接口
272
+ │ └── control_points.py # ControlPoint + EventType
273
+ └── registry/ # 注册中心集成(可选)
274
+ └── registry_client.py
275
+ ```
276
+
277
+ ## 许可证
278
+
279
+ Apache License 2.0