diff --git a/CHANGELOG.md b/CHANGELOG.md
index 215f7a96..a78cf6de 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,8 +18,7 @@ and full A2A-T extension support. Full A2A-T extension support and multi-protoco
extraction
- `ExtensionSender` / `DefaultExtensionSender`: one-shot pre-positioning facade for Authorization-T and Notification-T
(long-lived SSE subscription)
-- `ControlPoint` / `ExtensionCallback` split: flow decisions (`onTask` / `onSelfTask` / `onRoute` / `onNegotiation`) and
- reactive hooks (`onAuthorization` / `onNotification`) on separate interfaces
+- `ControlPoint` / `ExtensionSender` split: flow decisions (`onTask` / `onSelfTask` / `onRoute` / `onNegotiation`) on `ControlPoint`; Authorization-T / Notification-T pre-positioning on `ExtensionSender`
- `NegotiationStrategy`: pluggable clarification strategy injected into
`DefaultControlPoint`
- `SELF_LOOP` step type for local task handling without an A2A-T message
diff --git a/README.md b/README.md
index db1e420a..a6e34468 100644
--- a/README.md
+++ b/README.md
@@ -92,13 +92,15 @@ System.out.println("Success: " + result.isSuccess());
## Architecture
-```
-Layer 2 - Orchestration ExecutePsop
- | lifecycle, event stream, onFinish hook
-Layer 1 - Traversal WorkflowExecutor
- | DAG walk, parallel dispatch, context assembly, routing
-Layer 0 - Transport WorkflowEngineClient / A2ATransport
- A2A send, auth, extensions, SSL, SSE
+```mermaid
+graph TD
+ L2["Layer 2 — Orchestration
ExecutePsop
lifecycle, event stream, onFinish hook"]
+ L1["Layer 1 — Traversal
WorkflowExecutor
DAG walk, parallel dispatch, context assembly, routing"]
+ L0["Layer 0 — Transport
WorkflowEngineClient / A2ATransport
A2A send, auth, extensions, SSL, SSE"]
+ F["Foundation — Decision
ControlPoint
user-implemented business decisions"]
+
+ L2 --> L1 --> L0
+ L0 -.-> F
```
| Layer | Entry Point | Responsibility |
@@ -106,29 +108,38 @@ Layer 0 - Transport WorkflowEngineClient / A2ATransport
| High | `ExecutePsop.Builder` | Event stream, lifecycle, `onFinish` persistence |
| Mid | `WorkflowExecutor` | DAG traversal, context assembly, ControlPoint dispatch |
| Low | `WorkflowEngineClient` / `A2ATransport` | A2A send, auth, extensions, SSL, SSE normalization |
+| Foundation | `ControlPoint` | User-implemented business decisions (onTask, onSelfTask, onRoute, onNegotiation) |
## Package Structure
+```mermaid
+graph TD
+ root["dev.openan.workflow.engine"]
+ client["client
A2A transport, auth, extensions"]
+ control["control
User decision interfaces"]
+ core["core
DAG traversal, context assembly"]
+ model["model
Data models"]
+ registry["registry
LoadPsop, RegistryClient"]
+ runner["runner
ExecutePsop entry point"]
+
+ root --> client
+ root --> control
+ root --> core
+ root --> model
+ root --> registry
+ root --> runner
```
-dev.openan.workflow.engine
-├── client # A2A transport, auth, extensions (package-private internals)
-│ ├── WorkflowEngineClient # Send facade interface
-│ ├── DefaultWorkflowEngineClient # Send + Negotiation-T auto-loop
-│ ├── ExtensionSender # One-shot pre-positioning (Auth-T, Notification-T)
-│ ├── A2ATransport # Shared wire layer (runtime, auth, SSE)
-│ ├── AuthProvider # Custom auth provider interface
-│ ├── WorkflowEngineClientConfig # Builder config: SSL, auth, A2A-T
-│ ├── LlmHelper # LLM utility (wraps a2a-t-sdk LLMClient)
-│ └── CredentialCrypto # AES-256-GCM credential encryption
-├── control # User-facing decision interfaces
-│ ├── ControlPoint # onTask, onSelfTask, onRoute, onNegotiation
-│ ├── DefaultControlPoint # Default routing implementation
-│ ├── EventCallback # Event stream callback
-│ └── NegotiationStrategy # Pluggable negotiation clarification
-├── model # Data models (Workflow, Task, StepType, etc.)
-├── registry # LoadPsop, RegistryClient
-└── runner # ExecutePsop (entry point)
-```
+
+| Package | Key Classes | Description |
+|---------|-------------|-------------|
+| `client` | `WorkflowEngineClient`, `DefaultWorkflowEngineClient`, `ExtensionSender`, `A2ATransport`, `AuthProvider`, `AgentAuthManager`, `WorkflowEngineClientConfig`, `CredentialCrypto`, `AgentCardJacksonModule` | A2A transport, auth, extensions (package-private internals) |
+| `control` | `ControlPoint`, `DefaultControlPoint`, `EventCallback`, `EventType`, `NegotiationStrategy` | User-facing decision interfaces |
+| `core` | `WorkflowExecutor`, `ContextBuilder` | DAG traversal, context assembly |
+| `model` | `Workflow`, `WorkflowStep`, `Task`, `TaskRequest`, `TaskResponse`, `StepType`, `JumpCondition`, `RouteDecision`, `ExecutionResult`, `SendMessageResult`, `TaskStatus`, `WorkflowSearchResult` | Data models |
+| `registry` | `LoadPsop`, `RegistryClient` | PSOP loading and AgentCard registry |
+| `runner` | `ExecutePsop` | Entry point for workflow execution |
+
+> **Note:** `LlmHelper` lives in the **samples** module (`dev.openan.workflow.engine.examples`), not in the `client` package. The workflow engine itself does not call an LLM directly.
## Documentation
@@ -149,6 +160,8 @@ dev.openan.workflow.engine
- [Notification-T 设计分析](docs/zh/notification-t-design-analysis.md) - 长连接 SSE 设计选型
- [业务流](docs/zh/业务流.md) - SPN 跨城诊断业务流程
- [调用过程](docs/zh/调用过程.md) - 端到端报文交互示例
+- [工作台集成指南](docs/zh/工作台集成指南.md) - 工作台 Spring Boot 集成完整指南
+- [工作台 AgentScope 结合方案](docs/zh/工作台AgentScope结合方案.md) - AgentScope 框架结合方案
## Modules
diff --git a/docs/en/API_REFERENCE.md b/docs/en/API_REFERENCE.md
index f194cf64..f007b9dd 100644
--- a/docs/en/API_REFERENCE.md
+++ b/docs/en/API_REFERENCE.md
@@ -6,6 +6,7 @@
|-----------------------------------|-------------------------------------------------|
| `dev.openan.workflow.engine.client` | A2A message transport, auth, extensions, config |
| `dev.openan.workflow.engine.control` | User decision points and event system |
+| `dev.openan.workflow.engine.core` | DAG traversal engine and context assembly |
| `dev.openan.workflow.engine.model` | Data models (Workflow, Task, results) |
| `dev.openan.workflow.engine.registry` | PSOP loading and AgentCard registry |
| `dev.openan.workflow.engine.runner` | Entry point for workflow execution |
@@ -234,6 +235,55 @@ public interface A2AJavaClientRuntime {
A default implementation is provided. Implement this interface only if you need custom HTTP transport.
+### ConversationScopedA2AJavaClientRuntime
+
+Optional lifecycle callback for runtime implementations whose transport session spans multiple A2A requests (e.g. a gateway login that must stay alive across all negotiation rounds).
+
+```java
+public interface ConversationScopedA2AJavaClientRuntime {
+ void closeConversation(AgentCard agentCard, String contextId);
+}
+```
+
+When the runtime also implements this interface, the engine calls `closeConversation` after the full send + negotiation cycle completes — not after each individual HTTP request. This allows gateway sessions to be released only after the logical conversation is done.
+
+Implement alongside `A2AJavaClientRuntime`:
+
+```java
+public class MyGatewayRuntime
+ implements A2AJavaClientRuntime, ConversationScopedA2AJavaClientRuntime {
+ @Override
+ public Iterable sendMessage(...) { ... }
+
+ @Override
+ public void closeConversation(AgentCard agentCard, String contextId) {
+ // release gateway session
+ }
+
+ @Override
+ public void close() { ... }
+}
+```
+
+### AgentCardJacksonModule
+
+Jackson module for deserializing AgentCard JSON with security scheme normalization. Handles the OpenAPI-format `securitySchemes` / `securityRequirements` fields that the A2A SDK's strongly-typed `AgentCard` record expects.
+
+```java
+ObjectMapper mapper = new ObjectMapper()
+ .registerModule(new AgentCardJacksonModule());
+AgentCard card = mapper.readValue(
+ new File("agentcard/my_agent.json"), AgentCard.class);
+```
+
+### AgentCardNormalizer
+
+Utility that normalizes a raw `Map` (as returned by the Registry Center API) into the `AgentCard`-compatible format. Used internally by `RegistryClient.fetchAgentCards()`. Also available as a public static method for custom normalization:
+
+```java
+Map normalized = AgentCardNormalizer.normalize(rawMap);
+```
+
---
## dev.openan.workflow.engine.control
@@ -300,6 +350,7 @@ Override to receive real-time execution events. Event types are defined in `Even
| `STEP_COMPLETE` | A workflow step completed |
| `TASK_REQUEST` | A task was dispatched to an agent |
| `TASK_RESPONSE` | A task response was received |
+| `TASK_STATUS_CHANGED` | A task's status changed (pending → running → success/failed) |
| `AGENT_REQUEST` | A message was sent to an agent |
| `AGENT_RESPONSE` | A response was received from an agent |
| `AGENT_STATUS_UPDATE` | Agent SSE status update (SUBMITTED, WORKING, etc.) |
@@ -312,6 +363,7 @@ Override to receive real-time execution events. Event types are defined in `Even
| `AUTHORIZATION_RESOLVED` | Authorization decision was made |
| `NOTIFICATION` | Notification received from agent |
| `ROUTE_DECISION` | Route decision was made |
+| `WORKFLOW_COMPLETE` | The workflow completed (all steps finished) |
| `START` | Workflow execution started |
| `COMPLETE` | Workflow execution completed successfully |
| `ERROR` | Workflow execution failed |
@@ -371,6 +423,27 @@ Map registerAgentCard(Map agentCard)
---
+## dev.openan.workflow.engine.core
+
+### WorkflowExecutor
+
+Mid-layer DAG traversal engine. Walks the workflow steps, assembles upstream context via `ContextBuilder`, dispatches subtasks in parallel, applies step success policies (`ALL_SUCCESS` / `ANY_SUCCESS` / `SELF_LOOP`), and routes to the next step.
+
+Not typically instantiated directly by SDK users — `ExecutePsop` wraps it internally. Exposed for advanced integrations that need to run the traversal layer without the runner's lifecycle management.
+
+```java
+WorkflowExecutor executor = new WorkflowExecutor(
+ workflow, controlPoint, engineClient,
+ eventCallback, runtimeIntent, lang);
+ExecutionResult result = executor.run().join();
+```
+
+### ContextBuilder
+
+Package-private helper that assembles the context message for each step by folding upstream step outputs according to `contextFrom` rules (`"*"` = all ancestors, specific names = selective inheritance). Not part of the public API surface.
+
+---
+
## dev.openan.workflow.engine.model
### Workflow
@@ -403,6 +476,17 @@ Static factory: `Workflow.fromMap(Map)` parses from orchestratio
| `ANY_SUCCESS` | Any subtask success is sufficient |
| `SELF_LOOP` | The workflow agent handles the task locally via `onSelfTask`; no A2A-T message is sent. Success follows `ALL_SUCCESS`. |
+### TaskStatus
+
+Task lifecycle status, used in `TASK_STATUS_CHANGED` events for cross-SDK consistency with the Python SDK.
+
+| Value | String | Description |
+|-----------|------------|--------------------------------------|
+| `PENDING` | `"pending"` | Task created, not yet started |
+| `RUNNING` | `"running"` | Task in progress |
+| `SUCCESS` | `"success"` | Task completed successfully |
+| `FAILED` | `"failed"` | Task failed |
+
### Task
| Field | Type | Description |
@@ -511,3 +595,69 @@ Static factory: `Workflow.fromMap(Map)` parses from orchestratio
- Negotiation failures fall through after `maxNegotiationRounds`.
- Auth failures (401) are logged as `ERROR` and auth headers are not set; the request proceeds without auth.
- SSE stream errors after terminal events are logged at `DEBUG` level (expected behavior).
+
+---
+
+## spring-boot-starter Module
+
+The `spring-boot-starter` module provides Spring Boot auto-configuration for the A2A **server** side (not the client/workflow side). When on the classpath of a Spring Boot web application, it auto-registers all A2A SDK server components as Spring beans.
+
+### A2AProperties
+
+Configuration properties prefixed with `a2at.server`:
+
+| Property | Default | Description |
+|----------|---------|-------------|
+| `a2at.server.agent-card` | `classpath:agentcard.json` | Path to the AgentCard JSON file (classpath: or file: prefix supported) |
+| `a2at.server.path-prefix` | `/a2a/json` | URL path prefix for A2A endpoints |
+
+```yaml
+a2at:
+ server:
+ agent-card: classpath:agentcard/my_agent.json
+ path-prefix: /a2a/json
+```
+
+### A2AAutoConfiguration
+
+Auto-configures the following beans (all `@ConditionalOnMissingBean`, so you can override any):
+
+| Bean | Type | Purpose |
+|------|------|---------|
+| `agentCard` | `AgentCard` | Loaded from `a2at.server.agent-card` path via Jackson |
+| `a2aConfigProvider` | `A2AConfigProvider` | SDK configuration values |
+| `taskStore` | `InMemoryTaskStore` | In-memory task storage |
+| `eventBus` | `MainEventBus` | Event bus for SSE streaming |
+| `queueManager` | `InMemoryQueueManager` | Event queue manager |
+| `pushStore` | `PushNotificationConfigStore` | Push notification config storage |
+| `agentExecutorPool` | `ExecutorService` | Thread pool for agent execution (8 threads, daemon) |
+| `eventBusProcessor` | `MainEventBusProcessor` | Event bus processor |
+| `requestHandler` | `RequestHandler` | Default request handler |
+| `restHandler` | `RestHandler` | REST protocol handler |
+| `a2aController` | `A2AController` | Spring MVC controller (`message:send` + `message:stream`) |
+
+### A2AController
+
+Spring MVC controller that exposes A2A REST endpoints:
+
+- `POST {path-prefix}/message:send` — blocking send
+- `POST {path-prefix}/message:stream` — SSE streaming
+
+### Usage
+
+The partner only needs to provide an `AgentExecutor` implementation:
+
+```java
+@Component
+public class MyAgentExecutor implements AgentExecutor {
+ @Override
+ public ExecuteResult execute(ExecuteRequest request) {
+ // business logic
+ return ExecuteResult.builder()
+ .addTextPart("result text")
+ .build();
+ }
+}
+```
+
+All other beans (AgentCard, RequestHandler, RestHandler, A2AController, etc.) are auto-configured.
diff --git a/docs/en/DESIGN.md b/docs/en/DESIGN.md
index cba9ac1d..9f606f2c 100644
--- a/docs/en/DESIGN.md
+++ b/docs/en/DESIGN.md
@@ -80,8 +80,7 @@ concurrently, applies the step's success policy, and determines the next step (s
Step dispatch rules:
-- Steps whose predecessors are all satisfied are collected and dispatched in parallel (`asyncio.gather` /
- `CompletableFuture`), so steps at the same layer run concurrently.
+- Steps whose predecessors are all satisfied are collected and dispatched in parallel (`CompletableFuture`), so steps at the same layer run concurrently.
- Subtasks within a step also run in parallel.
- `ALL_SUCCESS` - all subtasks must succeed.
- `ANY_SUCCESS` - the first successful subtask wins; the rest are cancelled.
@@ -115,11 +114,6 @@ Authorization-T and Notification-T are pre-positioning concerns handled via `Ext
---
-## 4. A2A-T Extension Model
-means a host that only cares about routing does not have to implement (or stub) authorization hooks, and vice versa.
-
----
-
## 4. A2A-T Extension Model
Four A2A-T extensions are supported. They divide into two groups by lifecycle.
@@ -269,7 +263,7 @@ sequenceDiagram
---
-## 9. Dependencies
+## 8. Dependencies
**Java SDK:** `org.a2aproject.sdk:a2a-java-sdk-client` (A2A protocol),
@@ -279,7 +273,7 @@ The SDK is standalone: it does not depend on the orchestration center.
---
-## 10. Design Decisions Summary
+## 9. Design Decisions Summary
1. **Shared transport, two facades** - wire machinery written once on
`A2ATransport`; `WorkflowEngineClient` and `ExtensionSender` each own one orchestration concern and delegate wire
diff --git a/docs/en/DEVELOPER_GUIDE.md b/docs/en/DEVELOPER_GUIDE.md
index 1d79ab85..e4a06371 100644
--- a/docs/en/DEVELOPER_GUIDE.md
+++ b/docs/en/DEVELOPER_GUIDE.md
@@ -94,8 +94,10 @@ Events come from three layers: the runner (lifecycle bracket), the executor (ste
| `step_start` | executor | Step begins | `step` |
| `task_request` | executor | A subtask is dispatched to `onTask`/`onSelfTask` | `step`, `agent`, `task` |
| `task_response` | executor | `onTask`/`onSelfTask` returned a `TaskResponse` | `step`, `agent`, `task`, `output` |
+| `task_status_changed` | executor | Task status changed (pending → running → success/failed) | `step`, `agent`, `task`, `status` |
| `route_decision` | executor | Branch chosen | `step`, `next`, `reason` |
| `step_complete` | executor | Step finished | `step`, `results` |
+| `workflow_complete` | executor | All steps finished | `history`, `step_outputs` |
| `agent_request` | engine client | Message sent to agent | `agent`, `request`, `metadata` |
| `agent_response` | engine client | Response from agent | `agent`, `response` |
| `agent_status_update` | engine client | Agent SSE status update | `agent`, `state`, `is_final` |
@@ -205,22 +207,13 @@ Passwords can be AES-GCM encrypted with `enc::` prefix. The decr
### 7.2 Custom AuthProvider
For non-standard auth (SSO, API keys, custom headers):
-
```java
WorkflowEngineClientConfig.builder()
- .
-
-authProvider((agentName, agentCard, headers) ->{
- headers.
-
-put("Authorization","Bearer "+mySsoToken);
- headers.
-
-put("X-Custom","value");
+ .authProvider((agentName, agentCard, headers) -> {
+ headers.put("Authorization", "Bearer " + mySsoToken);
+ headers.put("X-Custom", "value");
})
- .
-
-build();
+ .build();
```
### 7.3 Credential File Fields
@@ -300,7 +293,7 @@ subscriber and let the future complete.
## 11. Checklist
1. Add Maven dependencies
-2. Implement `ControlPoint` (onTask + onSelfTask + onRoute)
+2. Implement `ControlPoint` (at minimum `onTask` + `onRoute`; `onSelfTask` and `onNegotiation` have defaults)
3. Get AgentCards (from registry or JSON files)
4. Load Workflow (via `LoadPsop` or build your own)
5. Configure `.env` and credentials file
diff --git a/docs/en/notification-t-design-analysis.md b/docs/en/notification-t-design-analysis.md
index 0a2521ca..dad4d835 100644
--- a/docs/en/notification-t-design-analysis.md
+++ b/docs/en/notification-t-design-analysis.md
@@ -18,6 +18,7 @@ The engine currently sends Authorization-T, Notification-T, and Task-T as three
calls. Each opens its own HTTP connection (SSE stream), gets a response, and closes.
```
+
```mermaid
sequenceDiagram
participant W as Workbench
@@ -37,7 +38,6 @@ sequenceDiagram
S-->>W: artifact (recovery result)
S-->>W: COMPLETED (stream closes)
```
-```
### Key Code Locations
@@ -105,6 +105,7 @@ stream open. When recovery completes, the SPN Agent pushes the result through th
disconnecting.
```
+
```mermaid
sequenceDiagram
participant W as Workbench
@@ -119,7 +120,6 @@ sequenceDiagram
S-->>W: SSE event: recovery result (via Notification-T stream)
W->>S: close connection (cancel subscription)
```
-```
### Authentication
@@ -192,15 +192,14 @@ This pattern is correct and requires no modification.
- SPN agent city2: samples/src/main/java/dev/openan/workflow/engine/examples/agents/SpnDomainAgentCity2Executor.java
- Workbench control: samples/src/main/java/dev/openan/workflow/engine/examples/agents/WorkbenchControlPoint.java
- Demo entry: samples/src/main/java/dev/openan/workflow/engine/examples/SpnCrossCityDiagnosisDemo.java
-- Agent server: samples/src/main/java/dev/openan/workflow/engine/examples/StartAgentsServer.java
+- Agent server: samples/src/main/java/dev/openan/workflow/engine/examples/embedded/StartAgentsServer.java
- E2E test: samples/src/test/java/dev/openan/workflow/engine/examples/SpnCrossCityE2ETest.java
- AgentCard city1: samples/src/main/resources/agentcard/spn_domain_agent_city1.json
- AgentCard city2: samples/src/main/resources/agentcard/spn_domain_agent_city2.json
- AgentCard workbench: samples/src/main/resources/agentcard/transport_workbench_agent.json
- Credentials: samples/src/main/resources/spn_agent_credentials.json
-- Workflow JSON: orchestration-center/data/workflow_storage/psop/psop_spn_cross_city_diagnosis.json
-- Protocol examples: workflow-exec-engine-java/protocol data example.txt
-- Protocol data example: workflow-exec-engine-java/调用过程.md
+- Workflow JSON: orchestration-center/data/workflow_storage/psop/psop_spn_cross_city_diagnosis.json (separate repo)
+- Protocol examples: docs/zh/调用过程.md
## Business Flow Definition (from business-flow.md / yewuliu.md)
@@ -223,6 +222,7 @@ This pattern is correct and requires no modification.
### Complete Business Flow
```
+
```mermaid
sequenceDiagram
participant U as Upper layer
@@ -255,7 +255,6 @@ sequenceDiagram
Note over W: SelfLoop: merge
W-->>U: merged result
```
-```
### Key Design Decisions (confirmed)
diff --git a/docs/zh/API_REFERENCE.md b/docs/zh/API_REFERENCE.md
index 2da03eca..a724d5a7 100644
--- a/docs/zh/API_REFERENCE.md
+++ b/docs/zh/API_REFERENCE.md
@@ -6,6 +6,7 @@
|-----------------------------------|---------------------------------------|
| `dev.openan.workflow.engine.client` | A2A 消息传输、认证、扩展、配置 |
| `dev.openan.workflow.engine.control` | 用户决策点和事件系统 |
+| `dev.openan.workflow.engine.core` | DAG 遍历引擎和上下文组装 |
| `dev.openan.workflow.engine.model` | 数据模型(Workflow、Task、Result 等) |
| `dev.openan.workflow.engine.registry` | PSOP 加载和 AgentCard 注册 |
| `dev.openan.workflow.engine.runner` | 工作流执行入口 |
@@ -230,6 +231,55 @@ public interface A2AJavaClientRuntime {
引擎提供默认实现。仅在需要自定义 HTTP 传输时实现此接口。
+### ConversationScopedA2AJavaClientRuntime
+
+可选的生命周期回调接口,适用于传输会话跨越多个 A2A 请求的运行时实现(例如网关登录需在所有协商轮次期间保持存活)。
+
+```java
+public interface ConversationScopedA2AJavaClientRuntime {
+ void closeConversation(AgentCard agentCard, String contextId);
+}
+```
+
+当运行时同时实现此接口时,引擎会在完整的发送 + 协商周期完成后调用 `closeConversation`——而不是每次 HTTP 请求之后。这样网关会话只会在逻辑会话结束后才释放。
+
+与 `A2AJavaClientRuntime` 一起实现:
+
+```java
+public class MyGatewayRuntime
+ implements A2AJavaClientRuntime, ConversationScopedA2AJavaClientRuntime {
+ @Override
+ public Iterable sendMessage(...) { ... }
+
+ @Override
+ public void closeConversation(AgentCard agentCard, String contextId) {
+ // 释放网关会话
+ }
+
+ @Override
+ public void close() { ... }
+}
+```
+
+### AgentCardJacksonModule
+
+用于反序列化 AgentCard JSON 的 Jackson 模块,包含安全方案归一化。处理 A2A SDK 强类型 `AgentCard` record 所需的 OpenAPI 格式 `securitySchemes` / `securityRequirements` 字段。
+
+```java
+ObjectMapper mapper = new ObjectMapper()
+ .registerModule(new AgentCardJacksonModule());
+AgentCard card = mapper.readValue(
+ new File("agentcard/my_agent.json"), AgentCard.class);
+```
+
+### AgentCardNormalizer
+
+将原始 `Map`(注册中心 API 返回)归一化为 `AgentCard` 兼容格式的工具类。`RegistryClient.fetchAgentCards()` 内部使用。也作为公共静态方法供自定义归一化使用:
+
+```java
+Map normalized = AgentCardNormalizer.normalize(rawMap);
+```
+
---
## dev.openan.workflow.engine.control
@@ -296,6 +346,7 @@ public class EventCallback {
| `STEP_COMPLETE` | 工作流步骤完成 |
| `TASK_REQUEST` | 任务分派给智能体 |
| `TASK_RESPONSE` | 收到任务响应 |
+| `TASK_STATUS_CHANGED` | 任务状态变更(pending → running → success/failed) |
| `AGENT_REQUEST` | 消息发送给智能体 |
| `AGENT_RESPONSE` | 收到智能体响应 |
| `AGENT_STATUS_UPDATE` | 智能体 SSE 状态更新 |
@@ -308,6 +359,7 @@ public class EventCallback {
| `AUTHORIZATION_RESOLVED` | 授权决策已做出 |
| `NOTIFICATION` | 收到智能体通知 |
| `ROUTE_DECISION` | 路由决策已做出 |
+| `WORKFLOW_COMPLETE` | 工作流完成(所有步骤结束) |
| `START` | 工作流执行开始 |
| `COMPLETE` | 工作流执行成功完成 |
| `ERROR` | 工作流执行失败 |
@@ -367,6 +419,27 @@ Map registerAgentCard(Map agentCard)
---
+## dev.openan.workflow.engine.core
+
+### WorkflowExecutor
+
+中层 DAG 遍历引擎。遍历工作流步骤,通过 `ContextBuilder` 组装上游上下文,并行分派子任务,应用步骤成功策略(`ALL_SUCCESS` / `ANY_SUCCESS` / `SELF_LOOP`),并路由到下一步。
+
+SDK 用户通常不直接实例化——`ExecutePsop` 内部封装了它。供需要在不含 runner 生命周期管理的情况下运行遍历层的高级集成使用。
+
+```java
+WorkflowExecutor executor = new WorkflowExecutor(
+ workflow, controlPoint, engineClient,
+ eventCallback, runtimeIntent, lang);
+ExecutionResult result = executor.run().join();
+```
+
+### ContextBuilder
+
+包级私有辅助类,按 `contextFrom` 规则折叠上游步骤输出,为每个步骤组装上下文消息(`"*"` = 所有前驱步骤,指定名称 = 选择性继承)。不属于公共 API 接口。
+
+---
+
## dev.openan.workflow.engine.model
### Workflow
@@ -399,6 +472,17 @@ Map registerAgentCard(Map agentCard)
| `ANY_SUCCESS` | 任一子任务成功即可 |
| `SELF_LOOP` | 工作流执行智能体通过 `onSelfTask` 本地处理,不发 A2A-T 消息。成功语义同 `ALL_SUCCESS`。 |
+### TaskStatus
+
+任务生命周期状态,用于 `TASK_STATUS_CHANGED` 事件,与 Python SDK 保持跨 SDK 一致性。
+
+| 值 | 字符串 | 说明 |
+|------------|------------|------------------------|
+| `PENDING` | `"pending"` | 任务已创建,尚未开始 |
+| `RUNNING` | `"running"` | 任务进行中 |
+| `SUCCESS` | `"success"` | 任务成功完成 |
+| `FAILED` | `"failed"` | 任务失败 |
+
### Task
| 字段 | 类型 | 说明 |
@@ -506,3 +590,69 @@ Map registerAgentCard(Map agentCard)
- 协商失败在 `maxNegotiationRounds` 轮后终止。
- 认证失败(401)记为 `ERROR` 日志,认证头不设置,请求继续发出。
- SSE 流在终态事件后的连接关闭日志为 `DEBUG` 级别(预期行为)。
+
+---
+
+## spring-boot-starter 模块
+
+`spring-boot-starter` 模块为 A2A **服务端**(非客户端/工作流侧)提供 Spring Boot 自动配置。当位于 Spring Boot Web 应用的 classpath 时,自动将所有 A2A SDK 服务端组件注册为 Spring Bean。
+
+### A2AProperties
+
+以 `a2at.server` 为前缀的配置属性:
+
+| 属性 | 默认值 | 说明 |
+|-------------------------|-------------------------------|-----------------------------------------------|
+| `a2at.server.agent-card` | `classpath:agentcard.json` | AgentCard JSON 文件路径(支持 classpath: 或 file: 前缀) |
+| `a2at.server.path-prefix` | `/a2a/json` | A2A 端点的 URL 路径前缀 |
+
+```yaml
+a2at:
+ server:
+ agent-card: classpath:agentcard/my_agent.json
+ path-prefix: /a2a/json
+```
+
+### A2AAutoConfiguration
+
+自动配置以下 Bean(均为 `@ConditionalOnMissingBean`,可覆盖任意一个):
+
+| Bean | 类型 | 用途 |
+|---------------------|-------------------------------|---------------------------------------------------|
+| `agentCard` | `AgentCard` | 通过 Jackson 从 `a2at.server.agent-card` 路径加载 |
+| `a2aConfigProvider` | `A2AConfigProvider` | SDK 配置值 |
+| `taskStore` | `InMemoryTaskStore` | 内存任务存储 |
+| `eventBus` | `MainEventBus` | 用于 SSE 流的事件总线 |
+| `queueManager` | `InMemoryQueueManager` | 事件队列管理器 |
+| `pushStore` | `PushNotificationConfigStore` | 推送通知配置存储 |
+| `agentExecutorPool` | `ExecutorService` | 智能体执行线程池(8 线程,守护线程) |
+| `eventBusProcessor` | `MainEventBusProcessor` | 事件总线处理器 |
+| `requestHandler` | `RequestHandler` | 默认请求处理器 |
+| `restHandler` | `RestHandler` | REST 协议处理器 |
+| `a2aController` | `A2AController` | Spring MVC 控制器(`message:send` + `message:stream`) |
+
+### A2AController
+
+暴露 A2A REST 端点的 Spring MVC 控制器:
+
+- `POST {path-prefix}/message:send` — 阻塞式发送
+- `POST {path-prefix}/message:stream` — SSE 流式
+
+### 用法
+
+合作方只需提供 `AgentExecutor` 实现:
+
+```java
+@Component
+public class MyAgentExecutor implements AgentExecutor {
+ @Override
+ public ExecuteResult execute(ExecuteRequest request) {
+ // 业务逻辑
+ return ExecuteResult.builder()
+ .addTextPart("result text")
+ .build();
+ }
+}
+```
+
+其余 Bean(AgentCard、RequestHandler、RestHandler、A2AController 等)均自动配置。
diff --git a/docs/zh/DESIGN.md b/docs/zh/DESIGN.md
index 017c9be1..052bd231 100644
--- a/docs/zh/DESIGN.md
+++ b/docs/zh/DESIGN.md
@@ -29,15 +29,15 @@ SDK 负责协议机制(消息发送、流式传输、认证、Task-T 提示词
SDK 分为四层,每层构建在下一层之上,单一职责,入口清晰。
-```
-Layer 2 - 编排层 ExecutePsop
- | 生命周期、事件流、取消、onFinish 持久化
-Layer 1 - 遍历层 WorkflowExecutor
- | DAG 遍历、并行下发、上下文组装、路由
-Layer 0 - 通信层 A2ATransport + 两个门面
- | WorkflowEngineClient(工作流发送)| ExtensionSender(一次性前置下发)
-基础层 - 决策 ControlPoint
- 用户实现的业务决策
+```mermaid
+graph TD
+ L2["Layer 2 - 编排层
ExecutePsop
生命周期、事件流、取消、onFinish 持久化"]
+ L1["Layer 1 - 遍历层
WorkflowExecutor
DAG 遍历、并行下发、上下文组装、路由"]
+ L0["Layer 0 - 通信层
A2ATransport + 两个门面
WorkflowEngineClient(工作流发送)| ExtensionSender(一次性前置下发)"]
+ F["基础层 - 决策
ControlPoint
用户实现的业务决策"]
+
+ L2 --> L1 --> L0
+ L0 -.-> F
```
### 2.1 Layer 0 - 通信层
@@ -237,7 +237,7 @@ sequenceDiagram
---
-## 9. 依赖
+## 8. 依赖
**本 SDK:** `org.a2aproject.sdk:a2a-java-sdk-client`(A2A 协议)、
`net.openan.a2at.sdk:a2a-t-client`(A2A-T 扩展)、Jackson、SLF4J、Lombok。
@@ -246,7 +246,7 @@ SDK 是独立的:不依赖编排中心。
---
-## 10. 设计决策总结
+## 9. 设计决策总结
1. **共享 transport,两个门面** — 通信层机制在 `A2ATransport` 上写一次;
`WorkflowEngineClient` 和 `ExtensionSender` 各自拥有一个编排职责,委托通信工作。
diff --git a/docs/zh/DEVELOPER_GUIDE.md b/docs/zh/DEVELOPER_GUIDE.md
index 5a65290c..8c4d7917 100644
--- a/docs/zh/DEVELOPER_GUIDE.md
+++ b/docs/zh/DEVELOPER_GUIDE.md
@@ -91,8 +91,10 @@ ExecutionResult result = ExecutePsop.builder()
| `step_start` | 执行器 | 步骤开始 | `step` |
| `task_request` | 执行器 | 子任务下发到 `onTask`/`onSelfTask` | `step`、`agent`、`task` |
| `task_response` | 执行器 | `onTask`/`onSelfTask` 返回 `TaskResponse` | `step`、`agent`、`task`、`output` |
+| `task_status_changed` | 执行器 | 任务状态变更(pending → running → success/failed) | `step`、`agent`、`task`、`status` |
| `route_decision` | 执行器 | 分支选择 | `step`、`next`、`reason` |
| `step_complete` | 执行器 | 步骤完成 | `step`、`results` |
+| `workflow_complete` | 执行器 | 所有步骤完成 | `history`、`step_outputs` |
| `agent_request` | 引擎客户端 | 消息发送到智能体 | `agent`、`request`、`metadata` |
| `agent_response` | 引擎客户端 | 收到智能体响应 | `agent`、`response` |
| `agent_status_update` | 引擎客户端 | 智能体 SSE 状态更新 | `agent`、`state`、`is_final` |
@@ -200,11 +202,11 @@ AgentCard card = mapper.readValue(json, AgentCard.class);
```java
WorkflowEngineClientConfig.builder()
- .authProvider((agentName, agentCard, headers) -> {
- headers.put("Authorization", "Bearer " + mySsoToken);
- headers.put("X-Custom", "value");
- })
- .build();
+ .authProvider((agentName, agentCard, headers) -> {
+ headers.put("Authorization", "Bearer " + mySsoToken);
+ headers.put("X-Custom", "value");
+ })
+ .build();
```
### 7.3 凭证文件字段
@@ -282,7 +284,7 @@ public Flux execute(@PathVariable String psopId) {
## 11. 检查清单
1. 添加 Maven 依赖
-2. 实现 `ControlPoint`(onTask + onSelfTask + onRoute)
+2. 实现 `ControlPoint`(至少 onTask + onRoute;onSelfTask 和 onNegotiation 有默认实现)
3. 获取 AgentCards(从注册中心或 JSON 文件)
4. 加载 Workflow(通过 `LoadPsop` 或自行构建)
5. 配置 `.env` 和凭证文件
diff --git a/docs/zh/notification-t-design-analysis.md b/docs/zh/notification-t-design-analysis.md
index cd767393..a384f839 100644
--- a/docs/zh/notification-t-design-analysis.md
+++ b/docs/zh/notification-t-design-analysis.md
@@ -59,7 +59,6 @@ Notification-T 和 Authorization-T 是 A2A-T 的前置扩展,在工作流启
Authorization-T 是一次性操作:下发策略 → 服务端确认 → 完成。不需要长连接。
流程:
-```
```mermaid
graph LR
ES["ExtensionSender.sendAuthorization"]
@@ -70,7 +69,6 @@ graph LR
ES --> TR --> SR --> ACK --> DONE
```
-```
### 3.2 Notification-T
@@ -78,7 +76,6 @@ Notification-T 需要长连接:订阅 → 流保持打开 → 后续结果通
设计选择:**在独立守护线程上维持长连接 SSE 流**。
-```
```mermaid
graph TD
ES["ExtensionSender.sendNotification"]
@@ -92,7 +89,6 @@ graph TD
ES --> TR --> DT --> ACK --> FUT --> OPEN --> PUSH --> END
```
-```
---
diff --git "a/docs/zh/\345\267\245\344\275\234\345\217\260AgentScope\347\273\223\345\220\210\346\226\271\346\241\210.md" "b/docs/zh/\345\267\245\344\275\234\345\217\260AgentScope\347\273\223\345\220\210\346\226\271\346\241\210.md"
index ea42407a..2205313b 100644
--- "a/docs/zh/\345\267\245\344\275\234\345\217\260AgentScope\347\273\223\345\220\210\346\226\271\346\241\210.md"
+++ "b/docs/zh/\345\267\245\344\275\234\345\217\260AgentScope\347\273\223\345\220\210\346\226\271\346\241\210.md"
@@ -53,26 +53,21 @@ A2A-T 执行引擎 SDK 和 AgentScope 解决的是完全不同层次的问题:
### 3.2 核心 API 表面
-```
-编排中心 (Python/FastAPI)
- | PSOP 工作流存储 + 搜索 API
- v
-LoadPsop.search() / load() <- 从编排中心搜索 + 加载工作流
- |
-ExecutePsop.builder() <- 高层工作流执行器(加载->执行->事件->持久化)
- .psop(workflow)
- .agentCards(cards)
- .controlPoint(cp) <- 工作台业务决策回调(AgentScope 插入点)
- .engineClient(client)
- .execute()
- |
- +- WorkflowEngineClient <- 出站发送门面(Task-T + 协商循环 + 认证)
- | +- sendMessage(agent, msg)
- |
- +- ExtensionSender <- 前置预定位门面(Authorization-T / Notification-T)
- | +- prePosition()
- |
- +- A2ATransport <- 底层传输(共享,两门面复用)
+```mermaid
+graph TD
+ ORCH["编排中心 (Python/FastAPI)
PSOP 工作流存储 + 搜索 API"]
+ LOAD["LoadPsop.search() / load()
从编排中心搜索 + 加载工作流"]
+ EXEC["ExecutePsop.builder()
高层工作流执行器(加载->执行->事件->持久化)
.psop(workflow)
.agentCards(cards)
.controlPoint(cp) ← 工作台业务决策回调(AgentScope 插入点)
.engineClient(client)
.execute()"]
+ WEC["WorkflowEngineClient
出站发送门面(Task-T + 协商循环 + 认证)
sendMessage(agent, msg)"]
+ EXT["ExtensionSender
前置预定位门面(Authorization-T / Notification-T)
prePosition()"]
+ TRANSPORT["A2ATransport
底层传输(共享,两门面复用)"]
+
+ ORCH --> LOAD
+ LOAD --> EXEC
+ EXEC --> WEC
+ EXEC --> EXT
+ WEC --> TRANSPORT
+ EXT --> TRANSPORT
```
### 3.3 工作台需要实现的三个组件
diff --git a/pom.xml b/pom.xml
index 6b8a941d..5cb24a24 100644
--- a/pom.xml
+++ b/pom.xml
@@ -36,9 +36,9 @@
- scm:git:git@github.com:Zhoujie628/a2at-engine-java.git
- scm:git:git@github.com:Zhoujie628/a2at-engine-java.git
- https://github.com/Zhoujie628/a2at-engine-java
+ scm:git:git@github.com:project-openan/workflow-engine-sdk-java.git
+ scm:git:git@github.com:project-openan/workflow-engine-sdk-java.git
+ https://github.com/project-openan/workflow-engine-sdk-java