Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
edfd071
fix(logging): decode printable ASCII unicode escapes in the wire display
Zhoujie628 Aug 31, 2026
d732d67
fix(logging): keep extension-URI business content visible in the wire…
Zhoujie628 Aug 31, 2026
fb31cb5
fix(samples): carry an explicit notification subscription condition
Zhoujie628 Aug 31, 2026
6c69760
test(samples): raise the offline LLM provider's fidelity to real judg…
Zhoujie628 Aug 31, 2026
8645e0c
docs: add the demo end-to-end A2A-T SDK call inventory to the guide
Zhoujie628 Aug 31, 2026
80004e8
docs: order the SDK call inventory by real business timing
Zhoujie628 Aug 31, 2026
3e9eb4c
docs: authorization and subscription go on their own channels, not wi…
Zhoujie628 Aug 31, 2026
47e678f
docs: fix mermaid sequence-diagram parse errors
Zhoujie628 Aug 31, 2026
b3f7b58
chore: remove dead code surfaced by a full reference audit
Zhoujie628 Aug 31, 2026
a11f691
refactor(model): avoid wildcard-capture inference in MessageContent s…
Zhoujie628 Aug 31, 2026
2f85392
style(model): drop redundant private on @Value class fields
Zhoujie628 Aug 31, 2026
3957dcd
refactor(samples): migrate off the deprecated A2ATErrorCodes constants
Zhoujie628 Aug 31, 2026
593aaa4
style: apply the shared Java formatting profile on main
Zhoujie628 Aug 31, 2026
f4e2c79
refactor: adopt dev's code cleanup on shared wire-log and transport f…
Zhoujie628 Aug 31, 2026
a204f65
fix(engine): harden cancellation, discovery deadlines and credential …
Zhoujie628 Aug 31, 2026
6264180
fix(samples): preserve terminal outputs and isolate execution lifecycles
Zhoujie628 Aug 31, 2026
3e73e3d
docs: publish host-neutral integration guidance and executable examples
Zhoujie628 Aug 31, 2026
f4394da
chore(release): require sample checks and sanitize build metadata
Zhoujie628 Aug 31, 2026
fc63df9
chore: keep local reference exclusions out of shared gitignore
Zhoujie628 Aug 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
# Copy this file to .env and fill in your values

# Full A2A protocol messages are emitted by the dedicated PROTOCOL DEBUG logger.
# Keep sensitive values hidden by default; set true only during controlled local debugging.
WORKFLOW_ENGINE_PROTOCOL_INCLUDE_SENSITIVE_HEADERS=false
# Credentials are always anonymized; there is no sensitive-header opt-in.
# Set false to omit request/response bodies; large bodies are truncated at this character count.
WORKFLOW_ENGINE_PROTOCOL_INCLUDE_BODY=true
WORKFLOW_ENGINE_PROTOCOL_MAX_BODY_CHARS=100000
Expand Down
15 changes: 11 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ name: CI

on:
push:
branches: [main]
branches: [ main ]
pull_request:
branches: [main]
branches: [ main ]
workflow_dispatch:

jobs:
build-and-test:
Expand Down Expand Up @@ -41,8 +42,7 @@ jobs:

samples-compilation-check:
runs-on: ubuntu-latest
name: Samples Compilation Check (optional)
continue-on-error: true
name: Direct sample release gate

steps:
- name: Checkout code
Expand All @@ -57,3 +57,10 @@ jobs:

- name: Build and test samples
run: mvn -B -pl samples -am verify

- name: Upload sample test reports
if: always()
uses: actions/upload-artifact@v4
with:
name: direct-sample-test-reports
path: samples/target/surefire-reports/
4 changes: 2 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"java.compile.nullAnalysis.mode": "automatic",
"java.configuration.updateBuildConfiguration": "interactive"
"java.compile.nullAnalysis.mode": "automatic",
"java.configuration.updateBuildConfiguration": "interactive"
}
159 changes: 19 additions & 140 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,149 +1,28 @@
# Changelog

## Unreleased — business callback boundary
## [Unreleased] — 1.0.0 release candidate

- Use published A2A-T 1.1.0 from Maven Central; remove SDK source checkout/install from CI; move content generation, validation, templates and SDK initialization to the host.
- Use published A2A-T 1.1.0 from Maven Central; remove SDK source checkout/install from CI; move content generation,
validation, templates and SDK initialization to the host.
- onTask returns final MessageContent; onNegotiation returns Send/Stop. Remove engine profiles and content handlers.
- Preserve complete ReceivedMessage and metadata layers alongside deterministic convenience outputs; keep local nested multi-output values.
- Deduplicate negotiation rounds, separate resource budgets from protocol rounds, and suppress late sends after timeout/cancellation.
- Preserve complete ReceivedMessage and metadata layers alongside deterministic convenience outputs; keep local nested
multi-output values.
- Deduplicate negotiation rounds, separate resource budgets from protocol rounds, and suppress late sends after
timeout/cancellation.
- Separate authorization/notification lifecycle from workflow outcomes; never synthesize a subscription ACK.
- Observe serialized HTTP/JSON-RPC, real gRPC metadata/protobuf and dev vendor SDK traffic with mandatory redaction and bounded SSE.
- Add local missing-port SpringSpnDemo negotiation tests for direct and dev Order; real LLM/platform/OMC validation remains separate.
- Observe serialized HTTP/JSON-RPC, real gRPC metadata/protobuf and dev vendor SDK traffic with mandatory redaction and
bounded SSE.
- Add local missing-port SpringSpnDemo negotiation tests for direct and dev Order; real LLM/platform/OMC validation
remains separate.
- Refresh bilingual callback, architecture and integration contracts. No older SDK compatibility layer.

All notable changes to this project will be documented in this file.
### Release hardening

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres
to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
- Propagate workflow cancellation and close execution-owned resources exactly once.
- Anonymize orchestration access tokens and bound registry response deadlines.
- Preserve multi-value results from arbitrary terminal workflow nodes.
- Publish a compiled host integration example and require sample regression tests.
- Keep documentation host-neutral; sample class and AgentCard identifiers remain unchanged.

## [Unreleased]

> Entries below older release headings describe those releases and are not current API contracts.

### Added

- Client TLS options for custom CA, mTLS client certificate/private key, encrypted PKCS#8 keys, and CRL checking
- Configurable bounded executors for client sends and Spring Boot server request handling
- Configurable Notification-T acknowledgement timeout and protocol-log body controls
- Pinned, unreleased A2A-T SDK revision with real offline SDK end-to-end coverage
- Explicit `NotificationSubscription` lifecycle/heartbeat handle and stable SDK-event mapper
- Structured Authorization-T and Notification-T generation, server validation, and whitelist/recovery sample callbacks
- WAIMO Task-T parsing plus two-city parallel diagnosis and exact-once merged workbench result

### Changed

- TLS configuration is now per client; it no longer changes JVM-wide hostname-verification properties
- Credential login uses the same TLS policy as agent traffic and encrypted credentials now fail closed
- AgentCards that declare security requirements now fail closed when neither matching credentials nor an `AuthProvider` is configured
- `securitySchemes` no longer implies non-empty `securityRequirements`; an `AuthProvider` can be the sole authentication source
- Notification-T distinguishes acknowledgement timeout from real stream failure and keeps its lifecycle independent from
workflow request transports
- Workflow execution validates graph targets and cycles up front and waits only for activated predecessors at joins
- Protocol headers are redacted by default; sensitive values require an explicit diagnostic opt-in
- Agent clients and transport executors are reused and closed through their owning runtime
- Task-T, Authorization-T, and Notification-T use independent transport/runtime/context instances
- Negotiation-T uses the latest stateless content APIs and canonical `negotiationContext`; removed SDK state-machine APIs are not used
- SDK `.env` paths remain instance-local instead of being copied into JVM-wide system properties
- Extension subscription and task-control capabilities are explicit interface contracts instead of
default methods that fail at runtime

### Fixed

- Task success is derived from the A2A task state instead of non-empty response text alone
- Conflicting authentication headers from `AuthProvider` and credential configuration now fail fast
- Extension URI matching now uses exact URI path segments instead of substring matching
- Notification callback implementations can no longer silently discard the supplied callback
- Header construction is split into isolated auth, credential, and extension contributors with conflict detection
- Protocol generation/validation failures now fail closed instead of sending raw text under an A2A-T URI
- Authorization-T rejection stops the independent authorization operation; add/modify/delete/query operations follow the SDK template contract
- Notification-T failed/canceled/rejected acknowledgements fail the subscription and callback failures cannot prevent cleanup
- Workflow joins merge all predecessor outputs deterministically and execute exactly once after active predecessors complete

## [1.0.0] - 2026-07-28

First public release. The SDK ships a clean transport-facade architecture with single-responsibility decision interfaces
and full A2A-T extension support. Full A2A-T extension support and multi-protocol transport.

### Added

- `A2ATransport`: shared wire layer owning the A2A client runtime, auth manager, agent-card map, and streaming event
extraction
- `ExtensionSender` / `DefaultExtensionSender`: pre-positioning facade for one-shot Authorization-T and long-lived
Notification-T SSE subscriptions
- `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
- `ANY_SUCCESS` step policy with early cancellation of remaining subtasks
- Parallel DAG step dispatch and context assembly (`ContextBuilder`)
- `EventType` constants covering runner lifecycle, step/task execution, agent traffic, and A2A-T extension events
- `ExecutePsop.Builder`: fluent builder with event stream, lifecycle bracket, and `onFinish` persistence hook
- `A2ATExtension` enum encapsulating all extension URIs (no hardcoded strings)
- `DefaultExtensionSender` prompt-generation dispatch (Task-T via the A2A-T SDK; Authorization-T / Notification-T /
Negotiation-T reserved for SDK support)
- [Design Document](docs/en/DESIGN.md) architecture document

### Changed

- `DefaultWorkflowEngineClient` is now a facade over `A2ATransport`, owning only the workflow send path (Task-T prompt
generation, Negotiation-T auto-loop, event callback, ControlPoint/ExtensionCallback wiring)
- Pre-positioning sends moved from `WorkflowEngineClient` to `ExtensionSender`
- `ExtensionRegistry` auto-registers only Task-T and Negotiation-T (in-workflow handlers); Authorization-T /
Notification-T are pre-positioning operations with request and subscription lifecycles respectively

## [0.3.0] - 2026-07-25

### Added

- `EnvFileLoader`: loads `.env` file entries into system properties, bridging A2A-T SDK's internal `.env` loading with
`CredentialCrypto` and other components that read from `System.getenv()` / `System.getProperty()`
- `ProtocolLogger`: dedicated `PROTOCOL` SLF4J logger for full protocol-level request/response dumps (headers + body),
enabling verification against real network captures
- `ExtensionInterceptor`: metadata-aware `A2A-Extensions` header injection; only advertises extensions actually present
in the current message metadata
- `AuthProvider` interface: custom authentication for non-standard auth mechanisms (SSO, API keys, custom headers)
- `sendExtensionMessage()` on `WorkflowEngineClient`: one-shot extension messages for Authorization-T pre-positioning
and Notification-T subscription
- `ExecutePsop.Builder`: fluent builder API replacing the 14-argument static
`execute()` method
- AgentCard Jackson module for deserializing AgentCard JSON with security scheme normalization
- HTTPS/TLS support with configurable verification and CA trust store
- AES-GCM credential encryption (`enc:iv:ciphertext` format) with
`A2AT_CRED_KEY` environment variable
- SSE timeout configurable via `sendTimeoutSeconds` (default 600s)
- Complete Chinese and English documentation:
- [Integration Guide](docs/en/INTEGRATION_GUIDE.md) / [中文](docs/zh/INTEGRATION_GUIDE.md)
- [API Reference](docs/en/API_REFERENCE.md) / [中文](docs/zh/API_REFERENCE.md)
- [Developer Guide](docs/en/DEVELOPER_GUIDE.md)
- [Contributing Guide](CONTRIBUTING.md)

### Changed

- `A2A-T extension content placed in artifact `metadata` (not `parts.text`)
per protocol specification in `调用过程.md`
- Negotiation-T metadata URI aligned with AgentCard declaration (uppercase, no `/v1` suffix)
- Negotiation text passed to SDK's `startNegotiation` uses short request text, not full task input
- AgentCard is now strongly typed (`org.a2aproject.sdk.spec.AgentCard`)
throughout the codebase; `List<?>` and `Map` replaced with typed equivalents
- Default SSL verify changed from `false` to `true` for production safety
- Default send timeout increased to 600 seconds (10 minutes)
- `DEVELOPER_GUIDE.md` moved from project root to `docs/`

### Fixed

- Authentication 401 failures caused by `A2AT_CRED_KEY` not being available to `System.getenv()` when `.env` file is
used (loaded by A2A-T SDK internally but not propagated to OS environment)
- All four extensions no longer injected into every request's
`A2A-Extensions` header; only active extensions are advertised
- `chunked transfer encoding, state: READING_LENGTH` errors after terminal SSE events downgraded to DEBUG level
(expected behavior)
- SDK `receiveNegotiation` "Unsupported negotiation type: FULFILLMENT"
warning downgraded to DEBUG (known SDK limitation, fallback works)

### Removed

- 14-argument static `ExecutePsop.execute()` method (replaced by Builder)
- `AgentCardMapper` (replaced by Jackson + `AgentCardJacksonModule`)
- Redundant blank lines in method bodies
- `AuthorizationTHandler` and `NotificationTHandler` (these are now pre-positioning operations done via
`sendExtensionMessage`, not part of the workflow extension handler chain)
This repository prepares the initial 1.0.0 SDK release. Earlier internal development notes are not published API
contracts or evidence of a Maven release. Release publication/tagging is a separate, explicitly authorized operation.
27 changes: 18 additions & 9 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Contributing to a2at-engine-java
# Contributing to workflow-engine-sdk-java

Thank you for your interest in contributing! This document covers the contribution process and coding standards.

Expand All @@ -11,16 +11,15 @@ Thank you for your interest in contributing! This document covers the contributi
## Development Setup

```bash
git clone git@github.com:Zhoujie628/a2at-engine-java.git
cd a2at-engine-java
mvn -o clean compile
mvn -o test
git clone https://github.com/project-openan/workflow-engine-sdk-java.git
cd workflow-engine-sdk-java
mvn -B clean verify
```

## Project Structure

```
a2at-engine-java/
workflow-engine-sdk-java/
|-- workflow-engine/ SDK engine module
| +-- src/main/java/dev/openan/workflow/engine/
| |-- client/ A2A transport, auth, extensions (package-private internals)
Expand Down Expand Up @@ -91,21 +90,21 @@ Every Java file must start with the Apache 2.0 license header:
- WARN: recoverable failures, fallbacks
- ERROR: auth failures, agent call failures
- Dedicated `PROTOCOL` logger for protocol-level request/response dumps
- No log truncation in demo/samples; full messages should be visible
- Always anonymize credentials; protocol bodies have configurable size limits and sensitive-data redaction

### Testing

- JUnit 5
- Unit tests for all public methods
- Integration tests for end-to-end workflows
- Run tests: `mvn -o test`
- Run the complete reactor: `mvn -B clean verify`; `-o` is only for a fully populated local dependency cache

## Commit Process

1. Fork the repository and create a feature branch
2. Write code following the standards above
3. Add/update tests
4. Run `mvn -o test` and ensure all tests pass
4. Run `mvn -B clean verify` and ensure all tests pass (including samples)
5. Add DCO signoff to your commit:
```
Signed-off-by: Your Name <your.email@example.com>
Expand Down Expand Up @@ -133,3 +132,13 @@ Every Java file must start with the Apache 2.0 license header:
- Use GitHub Issues
- Include: Java version, Maven version, error log, reproduction steps
- For protocol issues: include the `PROTOCOL` logger output

## Release acceptance

- Run the complete `mvn -B clean verify` reactor; sample failures block release.
- Documentation code snippets are compiled by DocumentedCallbackExampleTest; HostQuickStartTest executes the minimal host flow.
- Check default single-city negotiation, final serialized protocol logs, independent extension lifecycle, cancellation and secret anonymization.
- Verify published POM coordinates, sources/Javadoc artifacts and the absence of private configuration/reference documents.
- Record the tested commit and Surefire reports. Offline providers and local OMC simulators are not live acceptance.
- Live model/OMC validation requires authorized endpoints and a separate acceptance record. Never commit customer integration notes.
- Do not publish, tag, or push as a side effect of running tests.
16 changes: 9 additions & 7 deletions MAINTAINERS.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
# Maintainers

This file lists the maintainers of this repository. Maintainers have write access and are responsible for reviewing and merging contributions. Changes to this file are made by pull request and reviewed by the existing maintainers.
This file lists the maintainers of this repository. Maintainers have write access and are responsible for reviewing and
merging contributions. Changes to this file are made by pull request and reviewed by the existing maintainers.

| Organization | Name | GitHub Handle |
| ------------ | ---- | ------------- |
| Huawei | Fei Guo | @guofei66 |
| Huawei | Jie Zhou | @Zhoujie628 |
| Organization | Name | GitHub Handle |
|--------------|----------|---------------|
| Huawei | Fei Guo | @guofei66 |
| Huawei | Jie Zhou | @Zhoujie628 |

## Emeritus Maintainers

Maintainers who are no longer active but have made significant contributions to this repository.

| Organization | Name | GitHub Handle |
| ------------ | ---- | ------------- |
|--------------|------|---------------|
| (none yet) | | |

## Becoming a Maintainer

Maintainer status is granted by the existing maintainers of this repository, or by the TSC, based on a track record of sustained, quality contributions. To be considered, a contributor should demonstrate:
Maintainer status is granted by the existing maintainers of this repository, or by the TSC, based on a track record of
sustained, quality contributions. To be considered, a contributor should demonstrate:

- Consistent contributions over time (code, reviews, documentation)
- Understanding of the component's goals and architecture
Expand Down
Loading
Loading