DocsHow it works
Nini under the hood
Code reads the amount, Jev picks a registered service, the registry gives the payee, and Kimi writes the reply last.
Nini composes two narrow model roles around code that owns every fact. Jev classifies which registered service you meant. Kimi writes a short reply. Code reads the amount, routes the draft, resolves the payee and checks everything both models say. Neither model receives a way to move money.
#The pipeline
Each stage rejects a different kind of mistake, cheapest and most certain first. Everything before stage 2 runs before any model is called.
| Stage | What happens |
|---|---|
| 0. Catalog | Code works out who is asking and what they may pay or ask for: their approved services, and the other services registered on the network. A spender with no Active policy gets an answer about their policy, whatever they typed |
| 1. Code checks the sentence | A sentence containing an address is stopped here and never reaches a model. Another currency is refused. Code reads the dollar amount. No amount, several amounts or an unreadable amount become a question back to you |
| 2. Jev classifies | Jev sees your sentence and a closed set of service labels: approved and unapproved registered services together, with nothing marking which is which. It returns one service, a question between services, "nothing matches", or a decline. Below a confidence threshold it declines |
| 3. Code routes | Code looks up which list the chosen service is on. Approved becomes a payment draft. Registered but not approved becomes a draft request for owner approval, never a payment. Nothing registered becomes a question |
| 4. Amount lock | The draft's amount must equal the amount code read in stage 1. Any other figure is refused (amount-mismatch), never reconciled |
| 5. Resolution | The registry turns the service id into a payee on chain. Unknown, suspended and unreadable are three different answers, and only "unknown" blames the model |
| 6. Assembly | The draft is built from the session, the chain and the amount code read. The model contributed only the service's slug |
| 7. Narration | Only now, with everything locked, Kimi is asked for one or two sentences about the draft. Its text is checked and can only land in a display field |
#What Jev sees
Jev sees your sentence and the service labels. It never sees an address, calldata, a key or any method that can move money. It is never asked to pick, add or infer an amount.
#What Kimi sees, and how its reply is checked
Kimi receives a copy of the locked facts: the route (payment or approval request), the service's slug and registry name, the amount, the currency and the note, plus your sentence. It receives no address.
checkNarration then drops the reply whole, and a fixed plain sentence is shown instead, if it:
- is empty or longer than 500 characters
- contains an address
- contains markup
- contains instruction words such as "ignore" or "override"
- claims the money moved ("sent", "paid", "settled" and similar)
- names another currency
- states a dollar figure other than the locked amount, or several figures
- names a different service
- describes an approval request without mentioning approval
Dropping is always safe: the draft is unchanged and the shown sentence is plainer. Nothing parses the reply back, and the review card takes the service and amount from the locked draft, never from the reply.
#When a model is unavailable
- If Jev is unavailable, the server assembles no draft from anything else. It answers with the reason as a category (a timeout, out of credit, not configured), never the provider's own error text, and the app says it in plain words and offers Try again only where trying again can help.
- An exact name, without a model. When Jev could not answer, the app tries one narrow match with no model at all: the sentence must name a registered service exactly (its name or its id's words, never a description) and hold exactly one dollar amount, read by the same code as the server's. The service list is the registry's; an approved service becomes a payment draft, a registered one that is not approved becomes a request for the owner, and anything less certain stays unanswered. The reply says the draft was matched without the assistant. The payee still comes from the registry, the policy preview still runs, and the contract still decides.
- If Kimi is unavailable, slow or says something unsafe, the valid draft stays. You see the fixed sentence instead of Kimi's reply.
- A draft is judged on the account you have open. The app sends that account, and the server uses it only if the chain says you own it or hold a policy on it, the same rule as every other screen. Otherwise it refuses, and no model is asked.
#The draft has no recipient
The typed payment intent has no field for an address. The payee is read from the registry for the review card, and the contract resolves the service again when it pays. A hallucinated payee cannot be written down, and a hallucinated service id fails at the registry: an id nobody registered has nowhere to resolve to.
#Limits
- 6 requests a minute and 30 drafts in any 24 hours per person, counted from the first. A draft is only counted when a model is about to be asked, so a request refused before that costs nothing. A refusal says which limit and when it opens again.
- The route is switched on per deployment. Kimi is optional: without it, drafts still work and show the fixed sentence.