GitHub - goutamadwant/promptspecj: OpenAPI-style prompt contracts for Java and Spring AI. (original) (raw)

PromptSpec-J

PromptSpec-J is a contract-first library for prompts in Java applications. It treats prompts the way API teams treat OpenAPI contracts: as versioned, reviewable, validated, generated, and testable artifacts instead of anonymous strings embedded in service code.

What this library means in the AI ecosystem

Most of the AI application stack today is organized around runtime execution:

PromptSpec-J is not trying to replace any of those layers. It sits above the runtime framework and below the application business logic.

That means:

In practical terms, PromptSpec-J gives Java teams a way to say:

For Spring AI teams, PromptSpec-J acts as the missing governance layer around PromptTemplate, structured output conversion, and ChatClient. Spring AI already solves prompt rendering and model interaction well. PromptSpec-J makes those prompt definitions auditable, typed, and build-aware.

The problem PromptSpec-J solves

Prompt engineering in production Java services is usually still managed as string engineering.

A typical service today looks like this:

This produces a recurring set of engineering problems:

1. Placeholder drift

The prompt text changes, but the input map does not. Or the input object changes, but the prompt text does not. That failure is usually discovered only at runtime.

2. Output drift

A prompt that used to return one structured shape starts returning another. The runtime parser fails late, or worse, succeeds partially and produces degraded data.

3. Tool surface sprawl

As tool-calling expands, prompts can accidentally gain access to tools they were never meant to invoke because tool registration is handled close to runtime wiring rather than close to the prompt contract.

4. Review blindness

A pull request shows a changed prompt string, but not the implied impact on inputs, output schema, generated API shape, or compatibility expectations.

5. CI blindness

Teams can test controllers, repositories, and serializers in CI, but prompt behavior often remains outside the normal build discipline.

6. Release-train mismatch

Enterprise Java teams are used to typed interfaces, code generation, schema validation, and compatibility policies. Prompt logic usually bypasses all of that and lives as untyped runtime data.

PromptSpec-J solves this by moving prompt definitions into explicit contracts and making those contracts visible to the build, to generated code, and to automated tests.

How teams do this without PromptSpec-J today

Without a library like this, most teams assemble a fragmented workflow:

Prompt authoring

Output handling

Tool governance

Testing

Change management

This approach works for early prototypes. It does not scale well for backend teams that need repeatability, ownership, auditability, and CI-driven release control.

What PromptSpec-J changes technically

PromptSpec-J introduces a contract lifecycle:

  1. Define a prompt in YAML or JSON under src/main/promptspec/
  2. Validate the contract before code generation or compilation
  3. Generate stable Java APIs from the contract
  4. Execute through Spring AI using generated wiring
  5. Snapshot and diff prompt behavior in tests
  6. Track compatibility through a lockfile

The contract describes:

The validator enforces:

The code generator produces:

The test layer provides:

Architecture at a glance

Example contract

apiVersion: promptspec/v1alpha1 prompts:

Example generated shape

At generation time, PromptSpec-J produces a stable Java surface similar to:

public final class ArticleSummaryPromptInputs { private final String article;

public ArticleSummaryPromptInputs(String article) {
    this.article = article;
}

public String article() {
    return article;
}

}

public interface ArticleSummaryPrompt extends PromptContract<ArticleSummaryPromptInputs, String> { String execute(ArticleSummaryPromptInputs input); }

The generated client delegates to Spring AI runtime primitives instead of inventing a new chat abstraction.

Quickstart

  1. Add a contract under src/main/promptspec/.
  2. Add tools.yaml if the prompt uses a tool allowlist.
  3. Run ./gradlew promptSpecValidate promptSpecGenerate.
  4. Inspect the generated sources under build/generated/sources/promptspec/java.
  5. Use the generated client and metadata types in your application.
  6. Add snapshot tests for replayable CI drift detection.

The root repo tasks also validate and generate against the sample project in examples/spring-boot-demo.

Documentation

Current scope

The current implementation targets 0.1.0 and is intentionally narrow:

These are intentionally out of scope for the first release: