ADR-0013: An embeddable, governance-first agent SDK for Java teams (research + plan)¶
| Status | Proposed; phase 0 and the phase-1 artifacts implemented 2026-10-12 (see Progress) |
| Progress | 2026-10-12: sdk/java/ reactor created with agent-api, agent-core, agent-jdbc, agent-testkit, agent-spring-ai, agent-spring-boot-starter and agent-bom; mvn -f sdk/java/pom.xml verify is green (55 tests) on JDK 17 with Spring AI 2.0.1 and Boot 4.1.1; sources, javadoc and CycloneDX SBOM attached per artifact; flatten, enforcer, japicmp (skipped until a baseline exists) and the Central Portal release profile are configured. Decision change: every artifact is Java 17 (section 7.4 updated); the only local JDK was 17 and 17 widens adoption. Also done: examples/sdk/governed-tools (Spring Boot app with @Governed tools, approvals endpoint, H2 stores; its test runs without a model and passes against the installed SDK), the sdk CI job in .github/workflows/ci.yml (spotless on JDK 21, verify on JDK 17, reproducible-build diff, example compile, SBOM upload), sdk/java/README.md. Not done: namespace verification and first publish (7.1), core/ dogfooding (6.2), phases 2 and 3. Tooling note: google-java-format (any release) does not start on JDK 17.0.20's javac, so spotless runs on a JDK 21 (locally via JAVA_HOME, in CI as a separate setup-java step); the sources are formatted and spotless:check is clean. 2026-10-14: governance-gaps batch (all @Experimental): agent-scanner module (risk map, readiness score, --fail-under CLI gate); in agent-core the packages evidence (hash-chained and signed audit, EvidenceBundle, EU AI Act / OWASP ASI / underwriting exporters), autonomy (L1-L4 registry and gate), replay (PolicyReplay, ShadowGate, ShadowReport, PolicyDiff), mandate, halt (kill switch, drill, HaltStore SPI), provenance (manifest pinning, drift), cost (model, ledger, showback), memory (governed long-term memory, poison probe), journal reconciliation, approval notifier (Slack/Teams) and signed receipts; trace record/replay in agent-testkit; CompositeToolDispatchGate ordering halt, mandate, autonomy, provenance, policy; one-call switches on Governance.Builder. A review pass over the batch fixed 84 findings (attribute shadowing in the chain canonical form, chain resume, fail-closed autonomy/mandate/provenance paths, replay double counting, report injection). Docs: docs/sdk/compliance-mapping.md, security-review-pack.md, adoption-playbook.md, positioning.md; README "What's new" and "governance you can prove"; the examples/sdk/refund-agent/java example demonstrates autonomy demotion, a signed HashChainedAuditSink and the OWASP coverage report and runs against the installed snapshot. mvn -f sdk/java/pom.xml verify is green on JDK 17.0.20.1 (322 tests: api 20, core 230, jdbc 5, testkit 23, scanner 32, spring-ai 8, starter 4). spotless:check was not run locally in this pass (only JDK 17 installed; it runs on JDK 21 in CI). Not committed yet. |
| Date | 2026-10-12 |
| Deciders | Platform Engineering (maintainers) |
| Related | ADR-0011 provider plugins (the core-spi extraction and starter pattern), ADR-0012 Boot 4 / Spring AI 2 (the framework baseline the SDK must target), docs/plans/adr/coding-agent-harness.md, docs/plans/adr/step-journal-resumable-jobs.md, contracts/outbound/audit-event.schema.json |
Evidence rules. Code facts come from grep over
core/*/src/mainandcore/*/pom.xmlon 2026-10-12 (branchfeat/oss-site-mode). Nothing was compiled. External facts come from the sources in section 12, read on 2026-10-12;github.com,docs.langchain4j.devandopentelemetry.iocould not be fetched directly from this environment, so claims that rest only on secondary coverage are marked verify. Treat every verify as a phase-0 task.
1. Question¶
A maintainer asked: "Can we build something like dependencies that a Java dev team adds to their project to get agentic AI? Open source, standards followed, out of the box, something a corporate team must implement and must use."
Short answer: yes, but not as another "call the model" framework. Spring AI, LangChain4j,
Embabel, Google ADK and Koog already own model calls, tool loops and orchestration. What no
open-source Java library offers today is the control plane an enterprise reviewer asks for:
which tools an agent may reach, who approved a side-effecting action, what a run cost, whether a
replay is safe, one audit record across model calls, tool calls and approvals, and a mapping to
OWASP's agentic risk list and the EU AI Act. VegaDūta already has most of that in core/
(sections 3 and 4). The plan is to extract it as a small set of Maven Central artifacts that
sit on top of Spring AI (first) and LangChain4j (second), the way Embabel sits on Spring AI,
but for governance rather than planning.
Working name in this document: VegaDūta Agent SDK, Maven group io.github.cd-lc
(section 7.1 explains why the group is a phase-0 decision).
2. Context: what Java teams can already get (October 2026)¶
2.1 Frameworks¶
| Project | Status | What it gives | What it does not give (relevant to this ADR) |
|---|---|---|---|
| Spring AI 2.0.1 (GA 2026-06-12; 2.1.0-M1 2026-09-25) | GA | ChatClient, advisors, tool calling, MCP client/server (MCP Java SDK 2.x), observability via Micrometer. 2.0 moved the tool loop into a composable advisor and added context compaction. |
No approval gate, no budgets, no tool risk model, no audit schema. The Spring team says "the new agentic support" ships November 2026 as a separate project under Spring Projects Experimental, to be merged into Spring AI 3.0 "mid next year". Scope is not public. |
| spring-ai-agent-utils (community) 0.11.x | community | Agent Skills implementation, file/shell/web-fetch tools, memory utilities. verify version and licence. | Governance, approvals, budgets: not advertised. |
LangChain4j 1.22.x core, langchain4j-agentic 1.22.0-beta32 |
core GA; agentic beta | Framework-agnostic (Quarkus, Micronaut, plain Java). Sequence/parallel/loop/supervisor agents, AgenticScope, crash-resilient human-in-the-loop suspend/resume with AgenticScopeStore, compensation for tool actions, A2A client module, MCP client on spec 2026-07-28. |
Governance is per-workflow, not per-tool. No budgets, no tool risk classification, no audit schema, observability is "manual OTEL". verify against the official tutorial. |
| Embabel 1.0 (GA 2026-07, InfoQ 2026-08) | GA | GOAP planning over typed goals/actions/conditions, personas; Kotlin + Java; Apache-2.0; sits above Spring AI. | Built on Spring AI 1.1.7 / Boot 3.5 (Spring AI 2 support verify). No governance layer. |
| Google ADK for Java 1.0.0 (2026-03-30), later 1.x | GA (1.x); 2.0 GA for Java verify | A2A-centric multi-agent runtime, tight Gemini/Vertex integration. | Google-first; governance not a focus. |
| Koog 1.0 (JetBrains, KotlinConf 2026-05) | GA, 1-year API stability promise | Kotlin-first agents with Java support, multiplatform observability. | Kotlin idioms; no enterprise control plane. |
| Microsoft Agent Framework 1.0 (GA 2026-04) | GA for .NET and Python | Workflows, MCP, A2A, DevUI. | No Java SDK. |
| Jakarta Agentic AI 1.0 draft (M1, 2026-07-30) | draft spec, no RI or TCK yet | CDI-based @Agent with @Trigger/@Decision/@Action/@Outcome phases, a minimal LargeLanguageModel facade. |
Explicitly no tools, no memory, no provider APIs in 1.0. Not a competitor; a possible future adapter target. |
2.2 Governance and security tooling¶
| Project | Java? | Open source? | Notes |
|---|---|---|---|
| Microsoft Agent Governance Toolkit (2026-04-02) | No (.NET, TypeScript, Rust, Go, Python as of v3.3.0) | MIT | Claims coverage of all ten OWASP agentic risks, EU AI Act / HIPAA / SOC 2 evidence mapping. The nearest thing to this ADR, in every language except Java. |
AgentAdmit SDK com.agentadmit:agentadmit-sdk 1.5.1 |
Yes (Spring Boot) | Proprietary | "User-mediated AI agent authorization". Approval only. |
ai.deep-code:agents-kt 0.8.2 (2026-07) |
Kotlin/JVM | licence verify | "Permission manifests and audit evidence by construction". Early. |
AgentBudgetGuard 0.1.0 |
Yes | OSS | Spend limit wrapper for LLM calls and Spring beans. Pre-1.0, single concern. |
| OWASP Agent Control Standard (ACS) v0.1 (donated by Zenity 2026-05; under OWASP since 2026-09-01) | spec, not code | MIT | Defines middleware hook points at agent execution points, portable declarative policies, an Agent Bill of Materials (AgBOM). v0.1 public preview; hook names verify from the GitHub repository. |
Reading of the market. Orchestration is crowded and about to get more crowded (Spring AI Agents in November). Governance in Java is empty: the only full toolkit has no Java SDK, the only Java approval SDK is proprietary, and the budget and audit libraries are single-purpose and pre-1.0. This is the gap to fill.
2.3 Standards the SDK must speak¶
| Standard | Current version | Where it touches the SDK |
|---|---|---|
| MCP | 2026-07-28 (stateless core, server/discover, Multi Round-Trip Requests, cacheable list results, extensions framework, Roots/Sampling/Logging deprecated, DCR deprecated in favour of Client ID Metadata Documents, OTel traceparent in _meta) |
Tool argument/output hardening, origin pinning, secret redaction, timeouts; reuse the MCP Java SDK 2.x (managed by the Spring AI 2.0 BOM) rather than a transport of our own. |
| A2A | 1.0 (Linux Foundation, 2026-01/03), Java SDK org.a2aproject.sdk (Red Hat Quarkus/WildFly teams; last release 2026-04-17) |
Egress policy and card verification only; do not reimplement the protocol. |
| AG-UI | Java SDK com.ag-ui:* 0.0.1, client-side only; protocol "subject to change" |
Out of SDK v1. The platform keeps its server-side mapper. |
| Agent Skills (agentskills.io, 2025-12-18) | SKILL.md + YAML frontmatter, progressive disclosure; ~40 client implementations by mid-2026 |
Parser, integrity hash, supply-chain scan. |
| OpenTelemetry GenAI semantic conventions | gen_ai.* spans (invoke_agent, create_agent, execute_tool) are Development, not Stable, as of 2026-07 |
Emit them, pin the semconv version, document OTEL_SEMCONV_STABILITY_OPT_IN. |
| OWASP Top 10 for Agentic Applications 2026 (ASI01–ASI10, 2025-12-09) and ACS v0.1 | published / preview | Every control in the SDK is tagged with the ASI items it mitigates; hook points track ACS names once stable. |
| EU AI Act | Article 50 transparency in force 2026-08-02; stand-alone high-risk obligations deferred to 2027-12-02 by Regulation (EU) 2026/1744 (the "AI Omnibus", in force 2026-07-27) | AI-disclosure helper, log retention policy (high-risk deployers keep automatically generated logs for at least six months), human-oversight evidence from the approval trail. |
| ISO/IEC 42001, NIST AI RMF | management standards | A mapping document, not code. |
| Java library hygiene | Maven Central Portal (OSSRH retired 2025-06-30), mandatory signing, publishing limits enforced from 2026-10 (verify exact date), reproducible builds, CycloneDX SBOM, SLSA provenance, OpenSSF Scorecard, semver with japicmp, JSpecify nullness, JPMS module-info |
Section 7. |
3. What the platform already has (and how coupled it is)¶
All numbers from the tree on 2026-10-12.
3.1 Governance primitives that exist today¶
| Concern | Where | Shape | OWASP ASI it addresses |
|---|---|---|---|
| Tool dispatch policy | guardrails/ToolDispatchGate |
Verdict check(String toolName) with allow / deny / requireApproval |
ASI02 tool misuse, ASI05 code execution |
| Tool risk classification | agents/tools/classification/ToolClassification, ToolClassificationDecision (sealed: Classified / Blocked(UNCLASSIFIED, QUARANTINED)) |
requiresHumanConfirmation(), producesTaintedOutput(), isTaintSink(), requiresIdempotencyKey(), riskLabel() |
ASI01 goal hijack, ASI02, ASI06 memory poisoning |
| "Lethal trifecta" detection | agents/tools/LethalTrifectaDetector, TrifectaEnforcementService (warn / enforce modes) |
Blocks an agent that combines private-data read, untrusted input and an exfiltration sink | ASI01, ASI02, ASI07 |
| Guarded tool wrapper | guardrails/GuardedToolCallback (wraps Spring AI ToolCallback) |
Approval gate modes, procedure guard, step limits, Micrometer agent.tool.calls / agent.tool.errors |
ASI02, ASI08 cascading failures |
| Human approval | approval/HumanApprovalGateService, ApprovalRequest, ApprovalActionExecutor (+ registry), ApprovalDecisionAuthorizer, ApprovalReplayGrant, retry job |
Record, approve/reject with four-eyes authorisation, replay envelope, retry on executor failure | ASI09 human-agent trust |
| Run budgets | agents/tools/RunBudgetToolCallback, RunBudget, AgentRunBudgetService |
Per-run tool/token/cost budget, delegate usage recording | ASI08 |
| Idempotent effects and resumable steps | agents/tools/EffectJournal (+ DurableStore), StepJournal |
keyFor(runId, stepId, tool, args), lookup-before-call, durable-call begin/done |
ASI08 |
| Hooks (pre/post tool, webhook, rate-limited, redacted, fail-open/closed) | agents/hooks/* (27 files: HookPoint, HookEngine, HookMatcher, FailMode, HookRateLimiter, HookRedactor, HookWebhookClient) |
The nearest thing in the tree to ACS "middleware hooks" | ACS alignment |
| Content guardrails | guardrails/ContentGuardrail, ContentGuardrailEngine, PatternBasedGuardrailService (re2j), SemanticGuardrailService, toolargs/, procedures/ |
Input/output/tool-argument checks | ASI01, ASI06 |
| MCP hardening | agents/tools/McpToolOutputSanitizer, McpToolArgumentGuard, McpSecretRedactor, McpOriginPinning, NamespacedMcpToolCallback, SanitizedMcpToolCallback, EnvIsolatedStdioClientTransport, McpClientTimeoutConfig, RemoteMcpPreProbe |
Client-side defence against hostile or compromised MCP servers | ASI04 supply chain, ASI07 inter-agent |
| Skills supply chain | agents/skills/SkillMarkdownParser, SkillScanner, SkillScanRules, SkillIntegrity, SkillArchiveReader, SkillSupplyChainService |
Parse SKILL.md, hash, scan for prompt-injection and dangerous instructions |
ASI04 |
| Observability | chat/LlmMetricsAdvisor (OTel gen_ai.*), LlmCallLog, LlmRetry, ChatOptionsCopy, ProviderErrorTranslator |
Spring AI advisors | logging/evidence |
| Audit record | audit/*, wire shape already published as contracts/outbound/audit-event.schema.json |
evidence for EU AI Act / ISO 42001 | |
| A2A egress | agents/a2a/A2aEgressGuard, A2aCardVerifier, A2aCardSigningService |
Allow-list and signed cards for outbound agent calls | ASI07 |
3.2 Coupling that stands in the way¶
| Module | Main files | JPA entities | Files importing org.springframework |
Sibling deps |
|---|---|---|---|---|
| agents | 1043 | 49 | 533 | 24 modules |
| guardrails | 95 | 6 | 37 | json, approval, audit, tenancy |
| approval | 23 | 2 | 9 | audit, tenancy, security, rl, eventbus |
| audit | 35 | 4 | 12 | json |
| chat | 124 | 3 | 93 | audit, json, providers, security, tenancy |
Three facts drive the design in section 5:
- The governance classes are Spring AI-typed, not Spring-typed.
agentsreferencesorg.springframework.ai.tool.ToolCallback133 times andToolDefinition84 times, against 46 forChatClient. The wrapper pattern (GuardedToolCallback,RunBudgetToolCallback,SanitizedMcpToolCallback,HookingToolCallback) is one interface deep. A framework-neutralToolabstraction plus one adapter per framework covers it. - Tenancy and persistence are threaded through by concrete types.
TenantContext/TenantScope(security), JPA repositories (ApprovalRequestRepository,GuardrailRuleRepository,StepJournalRepository),@Valueproperties and MicrometerMeterRegistryappear inside the policy logic. The SDK must replace those with aRunContextrecord and store SPIs; the platform keeps its JPA implementations as adapters. - Platform-only concerns are mixed in. RL feedback (
approvaldepends onrl),IssueServicerecording, free-tier limits and theeventbuspublication belong to the product, not the library. They become decorators the platform applies around SDK types.
4. Decision drivers¶
- D1. Fill the real gap. Governance, not orchestration. A Java team that already uses Spring AI or LangChain4j must be able to add one dependency and keep their code.
- D2. Framework-neutral core, framework-specific adapters. The
apiandcoreartifacts depend on the JDK only (plus SLF4J). Spring AI, LangChain4j and Jakarta adapters are separate artifacts. - D3. Standards over invention. Reuse the MCP Java SDK, the A2A Java SDK, the Agent Skills format, OTel GenAI attributes, OWASP ASI identifiers and ACS hook names. Do not create a protocol or a DSL.
- D4. Corporate adoptability. Apache-2.0, Maven Central, signed and reproducible, SBOM
and provenance, semver with a public API gate, no transitive surprises, works under Spring
Boot AOT and GraalVM native image, Java 17 bytecode for the
apiartifact. - D5. Dogfooding is the proof.
core/must consume the SDK. A library the platform does not use will rot. - D6. Small team. Each phase ships something usable and reversible on its own.
5. Options considered¶
| # | Option | Verdict |
|---|---|---|
| A | Publish core/* modules as they are to Maven Central |
Rejected. They drag Spring Boot web, JPA, Postgres, tenancy and Keycloak into every consumer, and the Boot starter parent makes the POMs unpublishable without flattening. |
| B | Build a new orchestration framework (planner, DSL, multi-agent) | Rejected. It competes with Spring AI Agents (November), LangChain4j agentic, Embabel, ADK and Koog, and it is not where the platform's advantage is. |
| C | A single fat vegaduta-agent jar on Spring AI |
Rejected. Locks out Quarkus/LangChain4j users (D2) and ties the public API to Spring AI's release train. |
| D | Layered SDK: framework-free api + core, per-framework adapters, a Boot starter, a JDBC store, a test kit, a BOM |
Chosen. Mirrors how Spring AI and LangChain4j package themselves, and how ADR-0011 already splits core-spi from starters. |
| E | Contribute the governance layer upstream into Spring AI / LangChain4j instead | Deferred. Pursue after 1.0 for small pieces (for example a ToolDispatchGate advisor). Upstream cadence and scope are outside our control, and the framework-neutral core would be lost. |
| F | Separate GitHub repository from day one | Deferred. Start as a separate Maven reactor sdk/ in this repository so that core/ can dogfood unreleased changes in one PR. Split out once 1.0 ships, if contributors ask. |
6. Decision: the artifact set¶
All artifacts share the group io.github.cd-lc (decision, see 7.1), the version line 0.x until
the API freeze in phase 3, Apache-2.0, and a vegaduta-agent-bom.
| Artifact | Depends on | Contents (extracted from) | Java |
|---|---|---|---|
vegaduta-agent-api |
JDK, JSpecify | Interfaces, records, enums only: Tool, ToolCall, ToolResult, RunContext (tenant, principal, agentId, sessionId, runId, correlation), ToolDispatchGate + Verdict, ToolClassification + RiskLabel + ToolClassificationDecision, ApprovalGate / ApprovalStore / ApprovalDecisionAuthorizer / ApprovalActionExecutor, Budget / BudgetReservation, EffectJournal / StepJournal SPIs, ContentGuardrail + result types, HookPoint / HookDefinition / FailMode, AuditEvent (same shape as contracts/outbound/audit-event.schema.json) + AuditSink, GovernanceException hierarchy, AsiRisk enum (ASI01–ASI10) used as metadata on every control |
17 |
vegaduta-agent-core |
api, SLF4J; optional Micrometer, optional OTel API, Jackson | Default implementations: PolicyToolDispatchGate (allow-list, risk tiers, strict/warn modes), LethalTrifectaDetector, InMemoryApprovalStore + HumanApprovalGate with four-eyes rule, replay envelope and expiry, AtomicBudget (reserve-then-commit, safe under concurrent tool calls), InMemoryEffectJournal / StepJournal, PatternGuardrail (re2j), HookEngine with matcher, rate limiter, redactor and webhook client, GovernedToolDecorator (one wrapper composing gate, approval, budget, journal, hooks, audit, metrics), GenAiTelemetry (OTel gen_ai.* span and attribute helper, semconv version pinned), LogMasking |
21 |
vegaduta-agent-spring-ai |
core, spring-ai-client-chat (2.0.x; see 7.3) |
GovernedToolCallback (Spring AI ToolCallback adapter), GovernanceAdvisor (CallAdvisor/StreamAdvisor for budgets and content guardrails on ChatClient), ToolCallbackProvider decorator, LlmRetry, ChatOptionsCopy, ProviderErrorTranslator |
21 |
vegaduta-agent-spring-boot-starter |
spring-ai adapter, Boot autoconfigure | @AutoConfiguration with vegaduta.agent.* properties (mode strict/warn/off, risk defaults, approval expiry, budget defaults, OTel on/off), optional approval REST endpoints under /vegaduta/approvals (gated by a property), Actuator health and metrics, Spring Boot AOT hints |
21 |
vegaduta-agent-mcp |
core, MCP Java SDK 2.x | McpToolOutputSanitizer, McpToolArgumentGuard, McpSecretRedactor, McpOriginPinning, NamespacedTool, EnvIsolatedStdioTransport, timeout config, RemotePreProbe; aligned with MCP 2026-07-28 (stateless, server/discover, MRTR input_required handling as approval prompts) |
21 |
vegaduta-agent-skills |
core | SkillMarkdownParser, SkillDefinition, SkillIntegrity, SkillScanner + rules, archive reader; conforms to the Agent Skills spec |
21 |
vegaduta-agent-jdbc |
core, JDBC | Durable ApprovalStore, EffectJournal, StepJournal, AuditSink on plain JDBC; ships DDL for PostgreSQL and H2 as resources (db/vegaduta-agent/*.sql); no Flyway dependency, the host application owns migrations |
21 |
vegaduta-agent-langchain4j |
core, langchain4j-core |
ToolExecutor and guardrail adapters; agentic-module hooks once that module leaves beta |
21 |
vegaduta-agent-testkit |
core, JUnit 5, AssertJ | FakeModel, RecordingAuditSink, ScriptedApprover, GovernanceAssertions (assertThat(run).requiredApprovalFor("send_email"), .stayedWithinBudget(), .emittedAsiControls(ASI02)), replay fixtures, an ArchUnit rule set consumers can run ("no ToolCallback reaches the model ungoverned") |
21 |
vegaduta-agent-compliance |
core | EU AI Act Article 50 disclosure helper (system-prompt and response-metadata flags), RetentionPolicy (default 6 months for high-risk), AgBOM generator (JSON, from the tool manifest and classifications), ISO 42001 / NIST AI RMF / ASI mapping as resources |
21 |
vegaduta-agent-maven-plugin |
compliance | verify goal: fails the build if a @Tool is unclassified in strict mode, emits the AgBOM, checks SKILL.md integrity |
21 |
vegaduta-agent-bom |
Managed versions for all of the above plus the MCP and A2A SDK versions we test against |
Out of scope for 1.0: an orchestration DSL, an LLM client, a UI, runtime plugin loading
(ADR-0011 option C rationale applies), AG-UI server support, A2A protocol implementation
(reuse org.a2aproject.sdk; only A2aEgressGuard moves, into vegaduta-agent-mcp's sibling
vegaduta-agent-a2a in phase 3).
6.1 The out-of-the-box experience this must deliver¶
Target: a Spring Boot team goes from zero to a governed tool in under fifteen minutes.
<dependency>
<groupId>io.github.cd-lc</groupId>
<artifactId>vegaduta-agent-spring-boot-starter</artifactId>
</dependency>
@Component
class Payments {
@Tool(description = "Refund an order")
@Governed(risk = RiskLabel.HIGH, requiresApproval = true, idempotent = true)
String refund(String orderId, long cents) { ... }
}
With no further configuration, in warn mode (the default) the starter wraps every Spring AI
ToolCallback and: classifies it (unclassified tools are logged in warn, blocked in
strict), records an approval request instead of executing a requiresApproval tool,
reserves budget before the call, journals the effect key so a retried turn does not refund
twice, emits an AuditEvent and a gen_ai span, and runs any registered hooks. Approvals are
decided through ApprovalGate.approve(id, decidedBy) from the host app's own UI, or through the
optional starter endpoints. Everything persists in memory until vegaduta-agent-jdbc is on the
classpath.
6.2 How core/ consumes it (dogfooding)¶
guardrails,approval,agents/tools,agents/hooks,agents/skillskeep their REST controllers, JPA entities and tenant wiring, and delegate policy to SDK types. Their JPA repositories implement the SDK store SPIs.TenantContextis mapped toRunContextat the boundary (ChatTurnExecutor,AgentToolGuard).- Platform-only decorators (RL feedback,
IssueService, free-tier limits,eventbus) wrap the SDKApprovalGateandAuditSink. - The ArchUnit suite in
core/appgains a rule: no class incore/*may implementToolDispatchGateorApprovalGatelogic directly; it must use the SDK.
7. Decisions that need settling in phase 0¶
7.1 Group id and namespace¶
Maven Central namespace verification needs a domain or a GitHub handle. io.vegaduta
would need a DNS TXT on a domain we own; the project domain is vegaduta.ai, not
vegaduta.io. Settled: io.github.cd-lc, verified through a throwaway public repo in
the CD-LC organization (the portal issues a verification-key repo name and checks it
exists). Group id and Java package names (io.vegaduta.agent.*) intentionally differ: the
coordinates answer to the namespace we control, the packages keep the product name. Do not
use com.agenticai for published artifacts; it is the retired internal name (AGENTS.md
naming rule).
7.2 Repository layout¶
sdk/ first-party SDKs; typescript/ and python/ are the generated REST clients
sdk/java/ the Agent SDK: separate Maven reactor, own parent (NOT spring-boot-starter-parent)
pom.xml imports spring-ai-bom and spring-boot-dependencies as BOMs only
agent-api/ agent-core/ agent-spring-ai/ agent-spring-boot-starter/ agent-mcp/
agent-skills/ agent-jdbc/ agent-langchain4j/ agent-testkit/ agent-compliance/
agent-maven-plugin/ agent-bom/
examples/sdk/ governed-tools (Spring Boot), langchain4j-quarkus, plain-java
core/pom.xml depends on io.github.cd-lc:* at the reactor version. CI builds sdk/java/ first and
installs it (mvn -f sdk/java/pom.xml install), then core/; the "one Maven build at a time" rule
in AGENTS.md still holds. sdk/java/ gets its own tag prefix (sdk-v0.1.0) and release job.
7.3 Spring AI version for the adapter¶
The platform is on Spring AI 1.1.8 / Boot 3.5.16 (both OSS-EOL; ADR-0012 P2/P3 not started).
Publishing an adapter against 1.1.x would ship a dead line to new users. Decision: the
published vegaduta-agent-spring-ai targets Spring AI 2.0.x / Boot 4.x from the first
release. Until ADR-0012 P3 lands, core/ dogfoods api, core, mcp, skills and jdbc
(all framework-free) and keeps its own 1.1.x GuardedToolCallback as a thin shim. This makes
ADR-0012 a prerequisite for phase 2's "platform uses the Spring AI adapter" milestone, and is a
reason to schedule it.
7.4 Java baseline¶
Every artifact compiles to Java 17 bytecode (decided 2026-10-12, superseding the earlier
"api on 17, rest on 21" split). Boot 4's minimum is 17, Jakarta Agentic AI targets SE 17, and
17 is the floor most enterprises are on. Records and sealed types are available on 17; nothing
in the SDK needs virtual threads or pattern matching for switch. The platform's own core/
stays on 21.
7.5 Release hygiene checklist (all are phase-0 deliverables)¶
- Central Portal publishing with
central-publishing-maven-plugin; GPG signing now, Sigstore when Central accepts it. - Reproducible builds:
project.build.outputTimestamp, verified withmvn -Dreproducible verifyin CI (artifact rebuilt twice, checksums compared). - CycloneDX SBOM per artifact (
cyclonedx-maven-plugin), SLSA provenance via GitHubattest-build-provenance(the image pipeline in.github/workflows/release.ymlalready does this; reuse it). japicmpgate onapiandcore: no breaking change without a major bump after 1.0; a@Experimentalannotation for anything exempt.- JSpecify
@NullMarkedpackages;module-info.javainapiandcore; GraalVM reachability metadata incoreand the starter; Spring Boot AOT test in CI. - OpenSSF Scorecard already runs for the repository; add the Best Practices badge application.
javadocandsourcesjars; aCHANGELOG.mdsection per SDK release under a new## SDKheading, or a separatesdk/CHANGELOG.md(pick one in phase 0).
8. Phases¶
Each phase ends with a verification gate. "Done" means the gate passed, not that code exists.
Phase 0: foundations (about 2 weeks)¶
- Decide 7.1 to 7.5. Register the namespace. Create
sdk/withagent-api,agent-bomand the release workflow. Publish0.1.0-SNAPSHOTofagent-apito Central snapshots. - Resolve every verify in this document from primary sources: LangChain4j agentic API and licence, spring-ai-agent-utils scope, ACS hook names and AgBOM schema, OTel semconv status, Central publishing limits date, ADK Java 2.0 status, agents-kt licence.
- Gate: a consumer project with only
agent-apion the classpath compiles on Java 17; japicmp, reproducible-build check, SBOM and provenance jobs are green on the snapshot.
Phase 1: governed tools (about 6 weeks)¶
agent-core,agent-spring-ai,agent-spring-boot-starter,agent-jdbc,agent-testkit(minimum:FakeModel,RecordingAuditSink,ScriptedApprover).- Extract, in this order, with characterisation tests first (see
docs/engineering/CHARACTERISATION-TESTS.md):ToolDispatchGateand classification;GuardedToolCallbackintoGovernedToolDecorator; approvals; budgets (rewrite as reserve-then-commit: today'sagents/collab/RunBudgetsynchronises each method, butisExceeded()andrecord()are separate calls andrecordruns after the call, so two parallel tool calls can both pass the check and both overspend); effect and step journals; audit event; OTel helper. core/guardrailsandcore/approvalswitch to the SDK types (dogfood gate for framework-free artifacts).examples/sdk/governed-toolswith a README that a new user can follow in 15 minutes; time it with someone outside the team.- Gate: full
core/reactor green with the SDK in place; example app runs against Ollama with no key; approval and budget behaviour covered byagent-testkitassertions.
Phase 2: supply chain, hooks, second framework (about 6 weeks)¶
agent-mcp(requires MCP Java SDK 2.x, so this is the first module that forces the Spring AI 2.0 BOM; the platform keeps its 1.1.x MCP path until ADR-0012 P3),agent-skills, hooks inagent-core,agent-langchain4j,examples/sdk/langchain4j-quarkus.- Map
HookPointnames to ACS once its hook list is confirmed; publish the mapping. - Gate: an MCP server fixture that returns hostile output (prompt injection in tool results,
oversized payloads, secrets) is neutralised by
agent-mcpunder test; aSKILL.mdcorpus with known-bad skills is flagged; the LangChain4j example passes the sameagent-testkitassertions as the Spring one.
Phase 3: compliance, A2A guard, 1.0 (about 6 weeks)¶
agent-compliance,agent-maven-plugin,agent-a2a(egress guard and card verification on top oforg.a2aproject.sdk).- Documentation set: quickstart, "governance concepts" guide, ASI01–ASI10 control matrix, EU AI Act / ISO 42001 / NIST AI RMF mapping, migration notes for Spring AI Agents (whatever ships in November) and LangChain4j agentic GA.
- API freeze:
1.0.0ofapi,core,spring-ai,starter,jdbc,testkit; everything else stays0.xuntil it has two external users. - Gate: ADR-0012 P3 complete so that
core/runs on the published Spring AI adapter; japicmp baseline recorded; at least one outside project (a community user or a second internal service) on the 1.0 release candidate.
After 1.0¶
- Jakarta Agentic AI CDI adapter if the spec reaches a final 1.0 with a TCK.
- Upstream proposals: a
ToolDispatchGate-style advisor to Spring AI, a tool-classification guardrail to LangChain4j. - Split
sdk/into its own repository if contributor volume justifies it.
9. Consequences¶
Positive
- Java teams get, in one dependency, the controls that security and compliance reviewers ask
for, and keep Spring AI or LangChain4j for the model and the loop.
- The platform's governance code gains a public, versioned, tested API and loses its hidden
coupling to tenancy and JPA. ADR-0011's core-spi extraction and this SDK are the same work
seen from two sides.
- The project has a story that is distinct from every framework listed in section 2, and is
complementary to all of them.
Negative / costs
- A second reactor, a second release train and a public API contract to maintain.
- The platform must finish ADR-0012 (Boot 4 / Spring AI 2) to dogfood the Spring AI adapter.
- Some duplication during the transition: the 1.1.x shim in core and the 2.0 adapter in
sdk coexist for one or two releases.
Risks - Spring AI Agents (November 2026) ships approvals or budgets. Mitigation: the SDK is framework-neutral and positioned as the governance layer; adapt to their extension points instead of competing; evaluate within two weeks of their release and adjust phase 2. - OTel GenAI and ACS are still moving. Mitigation: pin versions, keep names behind our own enums, document the mapping, treat renames as minor releases before 1.0. - Namespace not obtainable. Mitigation: decide in phase 0 before any coordinates appear in documentation.
10. Success measures (review at the end of each phase)¶
| Measure | Target |
|---|---|
| Time from empty Spring Boot project to a governed, approval-gated tool, measured with a newcomer | under 15 minutes |
Transitive dependencies of agent-api / agent-core |
1 / under 5 (SLF4J, Jackson, JSpecify, optional Micrometer and OTel API) |
Classes in core/guardrails, core/approval, core/agents/tools replaced by SDK types |
over 60 percent of the rows in table 3.1 by end of phase 2 |
| OWASP ASI items with at least one SDK control and a testkit assertion | 10 of 10 by 1.0 |
| Public API breakage after 1.0 | zero without a major version (japicmp) |
| External adopters on a release candidate | at least one before 1.0 |
11. What this ADR does not decide¶
- Pricing, support tiers or a commercial edition. The SDK is Apache-2.0 like the platform.
- Whether the tenant console grows an "SDK" page. Not needed for the library.
- The internal naming of
RunContextfields beyond what section 6 lists; phase 1 settles it with the first consumer.
12. Sources (read 2026-10-12)¶
Frameworks and roadmaps - Spring AI 2.1.0-M1 announcement, with the November 2026 agentic-project statement: https://spring.io/blog/2026/09/25/spring-ai-2-1-0-M1-available-now/ - Spring AI 2.0.0 GA: https://spring.io/blog/2026/06/12/spring-ai-2-0-0-GA-available-now/; 2.0.1: https://spring.io/blog/2026/08/21/spring-ai-2-0-1-available-now/ - Spring AI Agent Skills post: https://spring.io/blog/2026/01/13/spring-ai-generic-agent-skills/ - Spring I/O 2026 framework comparison (Salm / Ahlgrimm): https://neatguycoding.com/posts/2026-05-18-spring-io-2026-comparing-agentic-ai-frameworks-for-java-by-timo-salm-sandra-ahlgrimm-sp/ - LangChain4j agents tutorial: https://docs.langchain4j.dev/tutorials/agents/; agentic workflows walkthrough: https://javapro.io/2026/07/08/langchain4j-agentic-workflows-from-ai-calls-to-multi-agent-systems-in-java/; Quarkus agentic extension: https://quarkus.io/extensions/io.quarkiverse.langchain4j/quarkus-langchain4j-agentic/ - Embabel 1.0 coverage: https://infoq.com/news/2026/08/embabel-1; https://www.besthub.dev/articles/spring-founder-returns-with-embabel-a-production-grade-java-agent-orchestration-framework-d12028024cbe - Google ADK for Java 1.0: https://developers.googleblog.com/announcing-adk-for-java-100-building-the-future-of-ai-agents-in-java/; releases: https://github.com/google/adk-java/releases - Koog 1.0: https://blog.jetbrains.com/ai/2026/05/koog-1-0-is-out-stable-core-better-interop-and-multiplatform-observability/ - Microsoft Agent Framework 1.0 (no Java): https://techcommunity.microsoft.com/blog/azuredevcommunityblog/the-future-of-agentic-ai-inside-microsoft-agent-framework-1-0/4510698; Copilot SDK note on Java: https://github.com/github/copilot-sdk/blob/main/docs/integrations/microsoft-agent-framework.md - Jakarta Agentic AI 1.0 draft: https://jakarta.ee/specifications/agentic-ai/1.0/jakarta-agentic-ai-1.0.0-M1.html; project announcement: https://payara.fish/blog/announcing-the-jakarta-agentic-ai-project - Other comparisons: https://codewiz.info/blog/java-ai-agent-frameworks-2026/, https://patotski.com/blog/spring-ai-vs-langchain4j/, https://dev.to/jamilxt/spring-ai-vs-langchain4j-in-2026-the-choice-got-harder-here-is-how-to-decide-429n
Governance tooling - Microsoft Agent Governance Toolkit: https://opensource.microsoft.com/blog/2026/04/02/introducing-the-agent-governance-toolkit/ - AgentAdmit SDK (proprietary): https://central.sonatype.com/artifact/com.agentadmit/agentadmit-sdk - agents-kt: https://mvnrepository.com/artifact/ai.deep-code/agents-kt/versions - AgentBudgetGuard: https://github.com/SarkarRana/AgentBudgetGuard; budget concurrency note: https://dev.to/erislandys/the-budget-that-actually-blocks-the-concurrency-bug-an-ai-agents-spend-guardrail-cant-afford-29gj; Oracle runtime budget guardrails: https://blogs.oracle.com/ai-and-datascience/runtime-budget-guardrails-agentic-ai - LangGraph4j human-in-the-loop: https://dev.to/bsorrentino/langgraph4j-implementing-human-in-the-loop-at-ease-565h
Standards - MCP 2026-07-28 changelog: https://modelcontextprotocol.io/specification/2026-07-28/changelog; announcement: https://blog.modelcontextprotocol.io/posts/2026-07-28/ - A2A Java SDK launch: https://quarkus.io/blog/a2a-project-launches-java-sdk; artifacts: https://badges.mvnrepository.com/artifact/org.a2aproject.sdk/a2a-java-sdk-spec/used-by - AG-UI Java SDK: https://docs.ag-ui.com/sdk/java/overview; https://javapro.io/2026/07/16/solving-spring-ais-ui-challenge-with-ag-uis-java-sdk/ - Agent Skills adoption: https://atlan.com/know/ai-agent/ai-agent-skills/what-are-agent-skills/; https://www.noqta.tn/en/news/skill-md-open-standard-30-ai-coding-tools-adoption-2026 - OpenTelemetry GenAI agent spans: https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-agent-spans; status discussion: https://dev.to/azena-ai/opentelemetrys-genai-semantic-conventions-are-not-stable-yet-heres-what-actually-shipped-in-2026-3mke - OWASP Top 10 for Agentic Applications 2026: https://genai.owasp.org/resource/owasp-top-10-for-agentic-applications-for-2026/; Agent Control Standard: https://genai.owasp.org/resource/agent-control-standard-acs/; CSA note: https://labs.cloudsecurityalliance.org/research/csa-research-note-owasp-genai-top10-2026-agent-control-stand/; Pillar on ACS v0.1.0: https://www.pillar.security/blog/standardizing-the-control-plane-for-ai-agents-pillars-role-in-acs-v0-1-0 - EU AI Act and the AI Omnibus (Regulation (EU) 2026/1744): https://www.addleshawgoddard.com/en/insights/insights-briefings/2026/technology/eu-ai-act-ai-omnibus-formally-adopted/; https://www.mondaq.com/eu-digital-omnibus-on-ai-enters-into-force/1825722; agents under Article 50: https://www.netskope.com/?p=76477; ISO 42001 / NIST AI RMF comparison: https://www.eccouncil.org/cybersecurity-exchange/responsible-ai-governance/eu-ai-act-nist-ai-rmf-and-iso-iec-42001-a-plain-english-comparison/ - Maven Central publishing limits and Portal: https://central.sonatype.org/publish/maven-central-publishing-limits/; https://community.sonatype.com/t/update-maven-central-publishing-limits-enforcement-moved-to-october-1/16475; Sigstore intent: https://www.sonatype.com/blog/maven-central-and-sigstore