Annotations · 3.0.0
Tool Classes
A tool class is a group of related operations the chat can call, declared once as a class with @Confiqure.Tool(name). It is the only place a tool can be declared — there are no method-level tools.
A tool class is a contract
- The class Javadoc is the business flow the chat follows — when to search, with which method, how to show the results, what a change needs, what to say after.
- Every public method is one typed operation — typed parameters and a typed return value.
nameis the tool class name. It defaults to the class name when blank.
/** FLOW: the seller's listings — find one, then change it.
* FIND: ask what they know (a title, an ASIN, or a code) and search with the matching
* method. One hit: confirm it. Several: show them as options and let the seller pick.
* None: say what was searched and ask for another clue.
* CHANGE: every change takes the sku of a found listing, never a typed one.
* Call, then say what changed. After a pick, "it" means that listing. */
@Confiqure.Tool(name = "ListingsTool")
@RestController
@RequestMapping("/api/confiqure/listings")
public class ListingsTool {
@PostMapping("/by-title") public List<Listing> byTitle(@RequestBody TitleQuery q) { ... }
@PostMapping("/by-asin") public List<Listing> byAsin(@RequestBody AsinQuery q) { ... }
@PostMapping("/quantity") public Ack setQuantity(@RequestBody QuantityChange c) { ... }
@Confiqure.Browser
public Ack openProduct360(@RequestBody SkuRef ref) { return null; } // runs in the page
}The chat model reads the class source and follows it. Nothing else is inferred.
Where an operation runs
Operations run on your server by default — a real controller method confiqure invokes over HTTP.
| Method carries | The operation |
|---|---|
| @PostMapping | Runs on your server. Its URL comes from Spring @RequestMapping + @PostMapping — a server operation needs no confiqure annotation. |
| @Confiqure.Browser | Runs in the host's page via the embed SDK. The method is a contract stub — its body never runs on the backend. Use it for anything that needs a UI: opening a view, a picker, OAuth. The signature still carries the I/O contract: the @RequestBody DTO is the input, the return type the output. Register its page handler keyed "ToolClassName.operationName" — see Embed Token & SDK. |
| @Confiqure.Async | Its result arrives later: confiqure ACKs the call immediately and you deliver the result afterwards. |
| any other mapping | Operations are @PostMapping only — a @GetMapping, @PutMapping or other mapping is refused at push. |
| neither | A public method with neither a mapping nor @Browser is a push error. |
@Confiqure.Async
The ai.confiqure:confiqure-spring SDK injects a ConfiqureCallback that does the header-reading and signed POST for you:
@Confiqure.Async
@PostMapping("/analyze")
public ResponseEntity<Void> analyze(@RequestBody SupplierQuery q, ConfiqureCallback reply) {
CompletableFuture.supplyAsync(() -> service.slowAnalysis(q))
.whenComplete((r, ex) -> { if (ex != null) reply.fail(ex.getMessage()); else reply.reply(r); });
return ResponseEntity.accepted().build(); // ACK now; the result follows
} Without the SDK, read the X-Confiqure-Tool-Call-Id and X-Confiqure-Reply-Url headers and POST {"result": …} back yourself. Use it only when the work outlives one request (long jobs, human-in-the-loop, webhooks); even a slow synchronous handler has a 5-minute window.
Arguments are checked against your types
The class declares the type; the engine converts and checks.
- Every argument is converted and checked against the declared parameter types before your method is called.
- Any text or id in an argument must appear in the user's words or in a tool result of the same conversation.
- An operation call is all-or-nothing: one rejected argument and nothing is POSTed.
What your operation receives
A server operation is an ordinary POST to your controller.
POST /api/confiqure/listings/quantity
X-Confiqure-Operation: setQuantity
X-Confiqure-End-User: <the end user's handle>
{ …the QuantityChange fields, and nothing else… }- The body is the operation's declared input DTO only — the canonical arguments, exactly as your
@RequestBodytype, so it binds with no wrapper. - The operation name rides the header
X-Confiqure-Operation, next to the end-user headerX-Confiqure-End-User. - Your reply is checked against the declared return type. A mismatch reaches the chat as "the tool answered with an unexpected shape", never as data.
- The model sees each operation as the function
ToolClass__operation(double underscore) — e.g.ListingsTool__setQuantity. The name may be at most 64 characters; a longer one is refused at push.
Tool classes are not attached to objects
There is no tools = anywhere. The chat brings a tool class into the conversation as its own tool frame when an ask needs it — exactly as it brings an object in as a setting frame. A screen can also open the chat with a tool class already loaded, through openingContext.toolClass.
To gate an operation on a record's values, put a @Confiqure.ToolGate on the object class:
@Confiqure.ToolGate(tool = "<operation>", requires = "…")Flows become tool classes
Configuration steps that are flows, not settings, become tool classes. Onboarding, for example, is an OnboardingTool class whose flow walks the user; the records it fills stay objects. You decide which of your endpoints are objects and which become tool classes — the goal is every feature and display of your frontend reachable as conversation.
Operations that need a yes
Since annotation 3.1.0, @Confiqure.Confirm on an operation that deletes, stops, pauses or cancels something, or changes something live (a live price), makes the call run only with confirmed=true. The engine shows the user a confirmation card first — text as its question, or its own words — and sets confirmed=true only from the user's yes: a click on the card, or a typed answer that one model call for that card reads as answering it; never from the chat model's own word. Without that yes the call is never made. @Confiqure.Confirm(false) turns the card off for that operation.
A tool class can also check values before they are set: see Validators & Verifiers.
Next:
Opening Context
Open the chat on a screen's records or a tool class.
Embed Token & SDK
Browser handlers for @Confiqure.Browser operations.