Skip to content

docs(spring-ai): reflect cycles-spring-ai-starter 0.3.0#635

Merged
amavashev merged 5 commits into
mainfrom
docs/spring-ai-starter-v0.3.0
May 13, 2026
Merged

docs(spring-ai): reflect cycles-spring-ai-starter 0.3.0#635
amavashev merged 5 commits into
mainfrom
docs/spring-ai-starter-v0.3.0

Conversation

@amavashev
Copy link
Copy Markdown
Contributor

@amavashev amavashev commented May 13, 2026

Summary

v0.3.0 of cycles-spring-ai-starter shipped to Maven Central earlier today (artifact verified live at repo1.maven.org/maven2/io/runcycles/cycles-spring-ai-starter/0.3.0/). The release adds three new extension points + an end-to-end integration test on top of v0.2.0. No breaking changes.

Files changed

  • changelog.md ecosystem table — cycles-spring-ai-starter row: 0.2.00.3.0, description rewritten to lead with the three new extension points and the 100/100 coverage marker.
  • how-to/integrating-cycles-with-spring-ai.md:
    • Maven and Gradle dep snippets bumped 0.2.00.3.0.
    • "What v0.2.0 covers" → "What v0.3.0 covers"; existing 0.2.0 bullets kept (drop-in compatible release); ObservationConvention bullet extended for the new cycles.reservation_id high-cardinality KeyValue.
    • New subsection "New extension points in v0.3.0" with code examples for SubjectResolver (tenant from SecurityContextHolder) and the jtokkit BPE opt-in (property + Maven dep snippet).
    • README link target #whats-new-in-020#whats-new-in-030.
    • SEO description frontmatter updated.
  • Removed stale "v0.2 will derive from prompt size" inline comment in the application.yml example — both ends of that path have shipped.

Verification

  • Maven Central confirmed live: maven-metadata.xml shows 0.3.0 as <latest> and <release>; all five 0.3.0 artifacts (pom, jar, sources, javadoc, GPG signature) respond 200.
  • No stale 0.2.0 spring-ai-starter references remain (grepped).

Test plan

  • Maven Central artifact live (no risk of 404 from a user following the dep snippet)
  • All v0.3 feature mentions cross-reference the right anchor in the starter README
  • Local docs preview renders cleanly
  • CI green on this branch

amavashev added 5 commits May 12, 2026 21:05
v0.3.0 of cycles-spring-ai-starter shipped to Maven Central on
2026-05-12 (artifact verified live at repo1.maven.org). The release
adds three new extension points (pluggable SubjectResolver, pluggable
PromptTokenEstimator with optional jtokkit BPE impl, cycles.reservation_id
on chat-client traces) and an end-to-end integration test, on top of
the v0.2.0 feature surface. No breaking changes vs v0.2.0.

Changes

- changelog.md ecosystem table: cycles-spring-ai-starter row bumped
  0.2.0 -> 0.3.0; description rewritten to lead with the three new
  extension points and the 100/100 coverage marker.

- how-to/integrating-cycles-with-spring-ai.md:
  - Maven and Gradle dep snippets bumped 0.2.0 -> 0.3.0.
  - "What v0.2.0 covers" section renamed to "What v0.3.0 covers".
    Existing 0.2.0 bullets kept (the features are still here, that's
    the point of a non-breaking minor); ObservationConvention bullet
    extended to note the new high-cardinality cycles.reservation_id
    KeyValue and the emit-reservation-id-on-trace opt-out.
  - New subsection "New extension points in v0.3.0" with:
      * SubjectResolver bean example for per-request attribution
        (tenant from SecurityContextHolder)
      * Property+dependency snippet for opting into jtokkit-based
        BPE token estimation
      * Pointer to the README's Extension Points section for full
        details
  - README link target #whats-new-in-020 -> #whats-new-in-030.
  - SEO description updated to mention v0.3.0 features (jtokkit,
    pluggable subject routing).

- application.yml example: dropped the stale "v0.2 will derive from
  prompt size" inline comment in favor of "set estimate-from-prompt=
  true to derive from prompt size" since both ends of that path are
  shipped.

Verification

- Maven Central confirmed live: maven-metadata.xml shows 0.3.0 as
  latest/release; all five 0.3.0 artifacts (pom, jar, sources,
  javadoc, GPG signature) respond 200 at repo1.maven.org.
- No stale 0.2.0 spring-ai-starter references left:
    grep -n "spring-ai-starter.{0,30}0\.2\.0" -> no matches
    grep -n "whats-new-in-020" -> no matches
Found by a review pass after the v0.3.0 framing changes. Eight stale
or inaccurate claims spread across two files; all in the
docs-fix-related-to-this-PR area, so bundling rather than opening a
separate cleanup PR.

how-to/integrating-cycles-with-spring-ai.md

- Comparison table (line ~19): "Spring AI CallAdvisor +
  ChatClientCustomizer (auto-wired)" was incomplete — streaming
  advisor + tool gate have been auto-configured since 0.2.0.
  Updated to: "Spring AI CallAdvisor + StreamAdvisor +
  ChatClientCustomizer (auto-wired); CyclesToolGate for per-tool
  gating".

- Comparison table "Where it intercepts" row: only mentioned .call()
  — also intercepts .stream() (auto) and tools (when wrapped).
  Updated.

- Comparison table "Call-site changes": clarified that tool wrapping
  is opt-in even though chat advisor attachment is transparent.

- Comparison table "Estimate computation" row: said
  "Fixed constant (v0.1.0); per-call derivation in v0.2". v0.2.0
  shipped chars/4 derivation; v0.3.0 made the estimator pluggable
  with a jtokkit BPE option. Rewritten to describe the current state.

- Comparison table: added a "Subject routing" row to mirror the
  pluggable SubjectResolver added in 0.3.0 (the boot starter side
  uses SpEL; the AI starter side uses a bean).

- Path-1 intro: "set 6 properties" was accurate at v0.1.0; with
  v0.3.0 the configuration surface is 13 properties. Rephrased to
  "configure a few cycles.* properties" without pinning a count
  (less likely to drift).

- "Don't double-charge" warning: README anchor
  #%EF%B8%8F-the-double-charge-gotcha didn't match the actual
  GitHub-rendered anchor (GitHub strips emoji + variation selectors
  from header anchors). Fixed to #the-double-charge-gotcha — the
  link now resolves.

- Path-2 "Prerequisites" dep snippet: Maven version pinned
  cycles-client-java-spring at 0.3.0 (doesn't exist; latest released
  is 0.2.2) and Gradle pinned 0.2.0 (also wrong). Both corrected to
  0.2.2 — what's actually live on Maven Central. These were stale
  before my v0.3.0 PR but surfaced in this review.

how-to/ecosystem.md

- "Spring AI Starter (advisor-based)" description: said the starter
  "auto-wires a CallAdvisor onto every ChatClient" — accurate at
  0.1.0, incomplete now. Updated to mention CallAdvisor +
  StreamAdvisor (both auto-wired), CyclesToolGate (opt-in per-tool),
  pluggable SubjectResolver, and the ObservationConvention's
  cycles.reservation_id emission.

No corresponding source-code claims; these are pure docs accuracy
fixes against the actual v0.3.0 surface that already shipped to
Maven Central.
…se case"

Review of quickstart/how-to-add-hard-budget-limits-to-spring-ai-with-cycles.md
against the v0.3.0 starter surface. The doc is conceptual (no Maven
coordinates, no property names, no code examples), so most v0.3.0
accuracy concerns don't apply. Three issues fixed:

1. Wrong starter link in Next steps

The "Next steps" section had a bullet:

    Integrate with Spring AI using the [Spring Client](
    https://github.com/runcycles/cycles-spring-boot-starter)

That's the wrong starter. cycles-spring-boot-starter is for generic
Spring Boot @cycles annotation use (non-Spring-AI code paths).
For Spring AI specifically, the canonical integration is
cycles-spring-ai-starter — which is exactly what this entire
guide is about. A reader following the guide's call-to-action would
end up at the wrong repo.

Rewrote the Next steps to:
- Lead with a "Start here" pointer to the existing
  /how-to/integrating-cycles-with-spring-ai guide (which has the
  concrete Maven setup, config reference, and v0.3.0 extension-point
  examples).
- Link cycles-spring-ai-starter as the actual starter, with a
  one-line note that cycles-spring-boot-starter is the companion
  for non-Spring-AI code paths (so readers who DO need that path
  still find it).
- Demoted the broader Cycles stack links into a separate "broader
  stack" group below — they were drowning the AI-specific guidance.

2. "Common first use case" was abstract about what "minimal
   architecture change" actually means

The doc said "guard every Spring AI model call with a Cycles
reservation ... gives you immediate value with minimal architecture
change". True but vague — a reader doesn't know if "minimal" means
"write a custom interceptor" or "annotate every method" or "add a
dep". Made it concrete: literally a Maven dep + a few cycles.spring-ai.*
properties; the auto-wired CallAdvisor + StreamAdvisor handle every
ChatClient call and stream without call-site changes.

3. Same section: per-tenant attribution was listed as "set the tenant
   in properties" implicitly

Mentioned that v0.3.0's SubjectResolver lets you pull tenant from an
authenticated principal at request time, not just from the
static-property defaults. Important for multi-tenant SaaS — the most
common case for hard-budget enforcement.

Also clarified that tool gating is opt-in (cyclesToolGate.wrap), not
auto-applied like chat — matches the actual v0.3.0 behavior and
avoids over-promising.
Two more issues from a deeper review pass on
how-to/integrating-cycles-with-spring-ai.md. (A third — significant
microcents math discrepancy — is flagged in the review summary but
intentionally not fixed in this commit; it needs to be addressed in
lockstep across the docs + the cycles-spring-ai-starter properties
javadoc and README, which is multi-repo coordination.)

1. Duplicate top-level `cycles:` key in the application.yml example

The Path 1 Configure example had two `cycles:` blocks at the top
level:

    cycles:
      base-url: ...
      tenant:   acme
      app:      my-spring-ai-app

    cycles:
      spring-ai:
        enabled: true
        ...

YAML's spec does not allow duplicate top-level keys. SnakeYAML
(Spring Boot's parser) tolerates this by merging or last-wins-ing,
but: (a) some other YAML tooling errors; (b) it's confusing to
readers who copy the snippet; (c) it suggests a structure
("cycles" appears twice") that isn't real. Merged into a single
top-level cycles: with spring-ai as a child node — the canonical
shape that any YAML parser handles correctly.

2. Next steps section pointed only at Path 2 resources

The "Next steps" at the end of the file linked exclusively to
cycles-spring-boot-starter resources (Quickstart, SpEL reference,
Spring Client configuration). A reader who followed Path 1 in this
guide would scroll to Next steps expecting AI-starter-specific
follow-ups and find none of them — the only AI-starter link was
the earlier "See README..." line in the body.

Split the Next steps into two groups:
  - Path 1 resources: cycles-spring-ai-starter README anchor (which
    has Extension Points, Quick Start, double-charge gotcha),
    Maven Central artifact link, and the existing strategic
    Budget Limits with Spring AI quickstart.
  - Path 2 resources: kept the existing four bullets verbatim.

This gives both readerships a place to go after finishing the
guide.

What's NOT in this commit (flagged for separate decision)

The cost-per-token examples used throughout the file (and the
cycles-spring-ai-starter properties javadoc / README) say:

    GPT-4o input  $2.50 / 1M tokens = 25  USD_MICROCENTS per token
    GPT-4o output $10.00 / 1M tokens = 100 USD_MICROCENTS per token

The Unit.java canonical definition says:
    1 USD = 100,000,000 microcents (i.e. 1 microcent = 1e-8 USD).

By that definition:
    $2.50 / 1M = 250  microcents per token (not 25)
    $10.00 / 1M = 1000 microcents per token (not 100)

So the examples are off by 10x — users who copy them set
estimates / actuals that under-bill by an order of magnitude.
The bug is in BOTH the docs site and the
cycles-spring-ai-starter source (CyclesSpringAiProperties.java
javadoc + README config-reference table). Needs coordinated fix
across both repos; not silently changing it in the docs alone
because that would create an inconsistency that's worse than the
status quo.
Companion to cycles-spring-ai-starter PR #30. The cost-per-token
examples in how-to/integrating-cycles-with-spring-ai.md and the
cycles-spring-ai-starter's own javadoc / README all said:

  GPT-4o input  $2.50/1M tokens = 25  microcents/token
  GPT-4o output $10.00/1M tokens = 100 microcents/token

Unit.java in the parent SDK is the canonical definition:
  "US dollars in microcents (1 USD = 100,000,000 microcents)"

Working through the conversion:
  $2.50 / 1M tokens × 100M microcents/USD = 250 microcents/token
  $10.00 / 1M tokens × 100M microcents/USD = 1000 microcents/token

So the examples are off by 10x. Users copying the snippets set
budgets that under-count actual provider cost by an order of
magnitude — budgets blow through silently because the accounting
under-reports.

Fifteen occurrences in this file, fixed atomically:
- Comparison table: `@Cycles("#tokens * 250")` (was * 25)
- jtokkit YAML opt-in block: input-cost-per-token: 250, output-cost-
  per-token: 1000 (was 25 / 100); added an inline comment on the
  input line spelling out the conversion (1 USD = 100M MICROCENTS)
  so future readers don't have to re-derive it.
- Ten SpEL @cycles(value = "#maxTokens * 250", ...) examples in
  Path 2 (was * 25)
- One @cycles(value = "#prompt.length() / 4 * 250", ...) example
- Two Java `maxTokens * 250L` / `tokenCount.get() * 250L`
  multiplications in the streaming-with-CyclesClient example
- Two comment lines on the gpt-4o examples updated to reflect the
  corrected microcent value

The starter-side PR (runcycles/cycles-spring-ai-starter#30) fixes
the property javadoc + README config-reference table in lockstep.
Both should land before any release notes or external content
references the existing wrong numbers.

Per-call dollar amounts in the file (e.g. `@Cycles("500000", // $0.005
per tool call ...)`) are NOT changed — they're correct ($0.005 =
500,000 microcents). Only the per-token factors are off.
@amavashev amavashev merged commit ebdac60 into main May 13, 2026
5 checks passed
@amavashev amavashev deleted the docs/spring-ai-starter-v0.3.0 branch May 13, 2026 01:26
@amavashev amavashev restored the docs/spring-ai-starter-v0.3.0 branch May 13, 2026 08:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant