bkper 5.4.1 → 5.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,201 +1,79 @@
1
1
  # Decision Models
2
2
 
3
- A decision model answers bounded questions about a state. Each answer is typed: the probability that a statement is true, one option from a set you define, or a level on a scale you define. The model writes no text. The model evaluates; your code decides.
4
-
5
- `POST /v1/decisions` serves decision models: models trained for calibrated decisions. [Jev](#jev-by-typesafe), from TypeSafe, is the first. The interface and its concepts come from TypeSafe's [System One](https://docs.typesafe.ai/concepts/system-one) API, and their documentation is a good companion to this page.
6
-
7
- ## When to use a decision model
8
-
9
- | When your code needs | Use |
10
- | ------------------------------------------------------------- | --------------------------------------------------------------- |
11
- | A yes/no, one of known options, or a level on a scale | A decision model |
12
- | Text, explanations, code, tool calls, or a custom JSON object | A [language model](https://bkper.com/docs/ai/ai-gateway.md#send-a-complete-request) |
13
-
14
- Why decision models suit accounting operations is covered in [AI Fundamentals](https://bkper.com/docs/ai/fundamentals.md#decision-models).
15
-
16
- ## How a request works
17
-
18
- A request has one **state** and one or more **questions**. The state is what the model judges: a string, JSON object, or array. Prefer an object with descriptive field names. Decision models currently read text only, so convert images and files to text first.
19
-
20
- The model evaluates each question independently, in parallel, against the same state, and returns one typed answer per question. There are three question types:
21
-
22
- - **`noul`** — _Is this true?_ Optional `criteria` describe what yes and no mean. Returns `noul`, the probability of yes from 0 to 1.
23
- - **`choice`** — _Which one of these?_ `criteria` maps 1–255 options to descriptions, or `null`. Returns the `choice` with `probabilities` and `confidence`.
24
- - **`score`** — _Which level on this scale?_ `criteria` lists 2–10 levels, lowest first. Returns a weighted `score` with `legend`, `probabilities`, and `confidence`.
25
-
26
- Ask one snap judgment per question — something a knowledgeable person decides in seconds. Split bigger judgments into several questions and combine the answers in code. Keep arithmetic, balances, and date comparisons in code too, and ask the model only the part that needs judgment. See TypeSafe's [Primitives](https://docs.typesafe.ai/primitives) and [State](https://docs.typesafe.ai/concepts/state).
27
-
28
- ## Send a request
29
-
30
- For an incoming bank line, this request asks three questions at once: which Account it belongs to, whether it is already recorded, and how urgently it needs review.
31
-
32
- ```bash
33
- curl --fail-with-body https://ai.bkper.app/v1/decisions \
34
- -H "Authorization: Bearer ${BKPER_TOKEN}" \
35
- -H "Content-Type: application/json" \
36
- -H "bkper-ai-source: my-app" \
37
- --data '{
38
- "model": "jev",
39
- "state": {
40
- "bank_line": {
41
- "date": "2025-03-11",
42
- "description": "AMAZON MKTPL*2K4LM",
43
- "amount": 89.90,
44
- "direction": "money out of Checking"
45
- },
46
- "existing_transaction": {
47
- "date": "2025-03-10",
48
- "amount": 89.90,
49
- "from": "Checking",
50
- "to": "Office Supplies",
51
- "description": "Printer toner, Amazon order 114-2K4LM",
52
- "origin": "manual entry"
53
- }
54
- },
55
- "questions": {
56
- "account": {
57
- "type": "choice",
58
- "instructions": "Which Account should receive the money that left Checking in `bank_line`?",
59
- "criteria": {
60
- "Cloud Hosting": "Servers, cloud infrastructure, storage, and hosting providers",
61
- "Software Subscriptions": "SaaS tools and per-seat software licenses",
62
- "Office Supplies": "Physical supplies and equipment for the office",
63
- "Travel": "Flights, hotels, ground transport, and meals while traveling"
64
- }
65
- },
66
- "already_recorded": {
67
- "type": "noul",
68
- "instructions": "Does `existing_transaction` already record the movement in `bank_line`?"
69
- },
70
- "review_priority": {
71
- "type": "score",
72
- "instructions": "How urgently should a bookkeeper review `bank_line`?",
73
- "criteria": [
74
- "Routine: consistent with normal activity",
75
- "Check: unusual but plausibly legitimate",
76
- "Urgent: large, unapproved, or suspicious"
77
- ]
78
- }
79
- }
80
- }'
81
- ```
3
+ A decision model judges; your code decides. It reads the facts your code gives it, such as a bank line, and answers narrow questions in a shape you set in advance: how likely something is true, which of your options fits, or where it sits on your scale. It writes no text, and it reports how sure it is as a number your code can compare.
82
4
 
83
- - **`model`** — any model with `type: "decision"` in [`GET /v1/models`](https://bkper.com/docs/ai/ai-gateway.md#model-ids). Each entry lists its `question_types`, `context_window`, and `max_state_question_tokens`.
84
- - **Question IDs** such as `account` are yours. Answers come back under the same IDs, but **IDs are not sent to the model**, so each `instructions` must stand on its own.
85
- - **Refer to state fields by name** in backticks, as in `` `bank_line` ``.
86
- - Each question accepts only `type`, `instructions`, and `criteria`. Instructions, descriptions, and levels can be strings or [structured JSON](https://docs.typesafe.ai/primitives/advanced).
87
-
88
- ## Read the response
89
-
90
- A real response to the request above:
91
-
92
- ```json
93
- {
94
- "model": "jev-1.13.0",
95
- "answers": {
96
- "account": {
97
- "type": "choice",
98
- "choice": "Office Supplies",
99
- "confidence": 1,
100
- "probabilities": {
101
- "Office Supplies": 1,
102
- "Cloud Hosting": 0,
103
- "Travel": 0,
104
- "Software Subscriptions": 0
105
- }
106
- },
107
- "already_recorded": {
108
- "type": "noul",
109
- "noul": 0.89
110
- },
111
- "review_priority": {
112
- "type": "score",
113
- "score": 0.09,
114
- "confidence": 0.86,
115
- "legend": {
116
- "0": "Routine: consistent with normal activity",
117
- "1": "Check: unusual but plausibly legitimate",
118
- "2": "Urgent: large, unapproved, or suspicious"
119
- },
120
- "probabilities": {
121
- "0": 0.91,
122
- "1": 0.09,
123
- "2": 0
124
- }
125
- }
126
- },
127
- "usage": { "input_tokens": 607, "output_tokens": 86 }
128
- }
129
- ```
5
+ Why that suits accounting is covered in [AI Fundamentals](https://bkper.com/docs/ai/fundamentals.md#decision-models). This page is about designing with decision models. [Jev](#jev-by-typesafe), by TypeSafe, is Bkper's first.
130
6
 
131
- Bkper validates every answer before returning it, so your code can rely on these guarantees:
7
+ ## When to use one
132
8
 
133
- - `answers` has exactly one entry per question ID, and each answer's `type` matches its question.
134
- - `choice` is always one of your `criteria` keys.
135
- - `score` is the probability-weighted level, from `0` to the number of levels minus one. It can fall between levels.
136
- - `probabilities` has one entry per option or level, and `legend` maps level indexes back to your text. Read both by key: order is not guaranteed, and values can be exactly `0` or `1`.
137
- - `confidence`, on choice and score answers, runs from 0 to 1 and is higher when probability concentrates on one answer. Noul answers have no `confidence`; the probability itself is the signal. See TypeSafe's [Confidence](https://docs.typesafe.ai/confidence).
138
- - `model` is the concrete revision that answered, such as `jev-1.13.0`.
9
+ | Your software needs | Use |
10
+ | ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
11
+ | A yes or no, one of known options, or a level on a scale | A decision model |
12
+ | Text, explanations, code, tool calls, or a custom JSON object | A [language model](https://bkper.com/docs/ai/models.md) |
13
+ | A conversation that works on Books, computes, and delivers files | An agent: [Bkper Agent](https://bkper.com/docs/ai/bkper-agent.md), or the [Managed Agent API](https://bkper.com/docs/api/managed-agent.md) in your app |
139
14
 
140
- Usage counts against your allowance at the model's [usage rates](https://bkper.com/docs/ai/models.md#usage-rates).
15
+ ## Where you use them
141
16
 
142
- ### Context changes confidence
17
+ - **In [Bkper CLI Agent](https://bkper.com/docs/ai/bkper-cli-agent.md#what-it-can-do)**, with no setup. Describe the outcome, such as "suggest Accounts for these bank lines and show me only the unsure ones", and the agent asks the decision model for you.
18
+ - **In apps and scripts**, with TypeSafe's SDK. See [Add Bkper AI to an App](https://bkper.com/docs/platform/apps/ai.md#ask-a-decision-model). The open-source [Merge Duplicates app](https://github.com/bkper/bkper-apps/tree/main/merge-duplicates) uses one to suggest duplicate pairs for a person to review.
143
19
 
144
- Ask about the same bank line without `existing_transaction`:
145
-
146
- ```json
147
- {
148
- "model": "jev",
149
- "state": {
150
- "bank_line": {
151
- "date": "2025-03-11",
152
- "description": "AMAZON MKTPL*2K4LM",
153
- "amount": 89.9,
154
- "direction": "money out of Checking"
155
- }
156
- },
157
- "questions": {
158
- "account": {
159
- "type": "choice",
160
- "instructions": "Which Account should receive the money that left Checking in `bank_line`?",
161
- "criteria": {
162
- "Cloud Hosting": "Servers, cloud infrastructure, storage, and hosting providers",
163
- "Software Subscriptions": "SaaS tools and per-seat software licenses",
164
- "Office Supplies": "Physical supplies and equipment for the office",
165
- "Travel": "Flights, hotels, ground transport, and meals while traveling"
166
- }
167
- }
168
- }
169
- }
170
- ```
20
+ ## Three kinds of question
171
21
 
172
- ```json
173
- {
174
- "model": "jev-1.13.0",
175
- "answers": {
176
- "account": {
177
- "type": "choice",
178
- "choice": "Office Supplies",
179
- "confidence": 0.75,
180
- "probabilities": {
181
- "Software Subscriptions": 0.14,
182
- "Cloud Hosting": 0.02,
183
- "Office Supplies": 0.81,
184
- "Travel": 0.02
185
- }
186
- }
187
- },
188
- "usage": { "input_tokens": 440, "output_tokens": 52 }
189
- }
190
- ```
22
+ Each question gets one typed answer:
23
+
24
+ | Ask | Example | You get |
25
+ | ---------------------------------- | --------------------------------------------- | ---------------------------------------------------- |
26
+ | **Is this true?** (`noul`) | Is this bank line already recorded? | The probability of yes, from 0 to 1 |
27
+ | **Which one of these?** (`choice`) | Which Account should receive this payment? | One of your options, with a confidence from 0 to 1 |
28
+ | **Where on this scale?** (`score`) | How urgently should someone review this line? | A position on your levels, with a confidence |
29
+
30
+ Confidence is high when the model's probability concentrates on one answer. For _Is this true?_, the probability itself is the signal. Ask several questions about the same facts in one request; the model answers each one independently.
31
+
32
+ ## Design a decision workflow
33
+
34
+ 1. **Find the judgment.**
35
+
36
+ Look for the step where a person glances and decides: which Account, is this a duplicate, does this need a second look. A good question is a snap judgment that a knowledgeable person makes in seconds.
37
+
38
+ 2. **Let code gather the facts.**
39
+
40
+ Code fetches the item and the context a person would need, such as nearby Transactions, how an Account is usually described, or Book and Account properties. Pass them as named fields, such as `bank_line` and `existing_transaction`. Decision models read text only, so convert files and images to text first.
41
+
42
+ 3. **Ask narrow questions.**
43
+
44
+ Ask one judgment per question. Split bigger judgments into several questions and combine the answers in code. Write each question in full: the model sees your instructions and the facts, never the name your code gives the question.
45
+
46
+ 4. **Keep calculation in code.**
47
+
48
+ Match amounts, compute date windows, and check balances in code, then ask the model only the part that needs judgment. For example, find Transactions with the same amount inside a date window, then ask only whether their descriptions describe the same movement.
49
+
50
+ 5. **Set thresholds by risk.**
191
51
 
192
- The top option is the same, but confidence drops from 1 to 0.75: the model reports that it is less sure.
52
+ Decide how sure the model must be before code acts. A missed suggestion costs a person a few seconds; a duplicate posting misstates a Book. Keep thresholds in one reviewable place.
193
53
 
194
- Give the model the context a person would need, such as nearby Transactions, how an Account is usually described, or Book and Account properties. Select that context in code. For example, find Transactions with the same amount inside a date window, then ask the model only whether the descriptions describe the same movement.
54
+ 6. **Act when confident; send the rest to a person.**
195
55
 
196
- ## Turn answers into decisions
56
+ Code acts on answers above the threshold and routes the rest to review. This is TypeSafe's [confidence-gated routing](https://docs.typesafe.ai/patterns/confidence-routing) pattern.
197
57
 
198
- An answer is a judgment, not permission to change a Book. Your code owns the thresholds and the actions, and sends uncertain cases to a person. This is TypeSafe's [confidence-gated routing](https://docs.typesafe.ai/patterns/confidence-routing) pattern:
58
+ 7. **Keep Book writes in code.**
59
+
60
+ An answer is a judgment, not permission to change a Book. When code posts, it records a normal Transaction, so the Book stays zero-sum whatever the model answered. Store the model revision and the confidence as Transaction properties for the audit trail.
61
+
62
+ 8. **Measure and adjust.**
63
+
64
+ Start with conservative thresholds and test them against your own records. Re-check them when the model's revision changes.
65
+
66
+ ## Putting it all together
67
+
68
+ A bank line arrives: `AMAZON MKTPL*2K4LM`, 89.90 out of Checking. Code finds a manual entry from the day before with the same amount, "Printer toner, Amazon order 114-2K4LM", and asks three questions at once. Jev answered:
69
+
70
+ | Question | Answer |
71
+ | --------------------------------------------------------------------------------------------------------- | ------------------------------ |
72
+ | Which Account should receive the money? Cloud Hosting, Software Subscriptions, Office Supplies, or Travel | Office Supplies, confidence 1 |
73
+ | Does the existing entry already record this movement? | Yes, with probability 0.89 |
74
+ | How urgently should a bookkeeper review it? Routine, Check, or Urgent | 0.09, Routine; confidence 0.86 |
75
+
76
+ Code then decides:
199
77
 
200
78
  ```ts
201
79
  // Keep questions and thresholds in one reviewable place.
@@ -232,86 +110,48 @@ export function decideBankLine(answers: BankLineAnswers): BankLineDecision {
232
110
  }
233
111
  ```
234
112
 
235
- The first response returns `check-duplicate`: the movement is probably already recorded. The bank line on its own, at 0.75 confidence, goes to `review`.
236
-
237
- When your code does post, it creates a normal Transaction from `Checking` to the chosen Account, so the Book stays zero-sum whatever the model answered. The risks to control are a wrong Account and a duplicate movement, which is why those checks come before posting. Store `model` and `confidence` as Transaction properties for the audit trail.
238
-
239
- Start with conservative thresholds, test them against your own records, and re-check them when the returned `model` changes. For more designs, see TypeSafe's [Patterns](https://docs.typesafe.ai/patterns) and [Cookbooks](https://docs.typesafe.ai/cookbooks), and the open-source [Merge Duplicates app](https://github.com/bkper/bkper-apps/tree/main/merge-duplicates), which suggests duplicate pairs for human review.
240
-
241
- ## Call from code
242
-
243
- TypeSafe's JavaScript SDK, `@typesafe-ai/sdk`, works with Bkper AI and infers answer types from your questions. Any other HTTP client can call `POST /v1/decisions` directly:
113
+ These answers return `check-duplicate`: the movement is probably already recorded, so code posts nothing. When code does post, it records a Transaction from Checking to the chosen Account. The risks to control are a wrong Account and a duplicate movement, which is why those checks come first.
244
114
 
245
- - **In a Bkper Platform app Worker**, send no `Authorization` header. Platform outbound adds authorization and app attribution.
246
- - **In scripts and servers**, send your own Bkper access token as a bearer token.
247
- - **In a browser page**, send the signed-in user's access token. Any origin may call, usage counts against that user's allowance, and the user can see your questions. See [Call from a browser](https://bkper.com/docs/ai/ai-gateway.md#call-from-a-browser).
248
- - **In [Bkper CLI Agent](https://bkper.com/docs/ai/bkper-cli-agent.md#what-it-can-do)**, no setup is needed. Describe the outcome and the agent asks the decision model for you.
115
+ The exact request and response are in the [AI Gateway API guide](https://bkper.com/docs/api/ai-gateway.md#decision-models).
249
116
 
250
- See [Add Bkper AI to an App](https://bkper.com/docs/platform/apps/ai.md#ask-a-decision-model) for the SDK setup in both cases and its limits with Bkper AI.
251
-
252
- ## Errors and retries
253
-
254
- Errors use the same envelope as every [Bkper AI endpoint](https://bkper.com/docs/ai/ai-gateway.md#errors). Branch on `error.code`, not only on the HTTP status:
117
+ ### Context changes confidence
255
118
 
256
- ```json
257
- {
258
- "error": {
259
- "message": "Unknown field: questions.route.threshold.",
260
- "type": "invalid_request_error",
261
- "param": "questions.route.threshold",
262
- "code": "invalid_request"
263
- }
264
- }
265
- ```
119
+ Ask about the same bank line without the manual entry, and the answer changes:
266
120
 
267
- | Status | `error.code` | What to do |
268
- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
269
- | `400` | `invalid_request`, `missing_model`, `unsupported_model`, `invalid_state`, `invalid_questions`, `invalid_question`, `unsupported_question_type` | Fix the field named in `error.param`. Do not retry unchanged. |
270
- | `400` | `provider_rejected` | The model rejected the request. Check its size against the model's limits. |
271
- | `401`–`403` | `unauthorized`, `billing_overdue`, `entitlement_unavailable` | Fix authentication or account access. Do not retry. |
272
- | `429` | `usage_limit_exceeded` | The monthly allowance is exhausted. Do not retry. |
273
- | `429` | `provider_rate_limited` | Retry with backoff. Honor `retry-after` when present. |
274
- | `503` | `provider_overloaded`, `usage_unavailable` | Retry with backoff. Honor `retry-after` when present. |
275
- | `502` | `provider_error`, `provider_rejected` | Retry a limited number of times, then fail. |
121
+ | Facts given | Which Account? |
122
+ | ----------------------------------- | --------------------------------------------------------------------- |
123
+ | The bank line and the manual entry | Office Supplies, confidence 1 |
124
+ | The bank line alone | Office Supplies, confidence 0.75, with 0.14 on Software Subscriptions |
276
125
 
277
- ## Caching
126
+ The top option is the same, but the model reports that it is less sure, so `decideBankLine` sends the line to review. Give the model the context a person would need.
278
127
 
279
- Bkper caches decision results for 15 minutes per user. An identical request in that window returns the same answers without calling the model or consuming allowance, and repeats the original `usage`. Aliases of the same model share one cache entry. To get fresh answers, change the request or wait. See [Privacy, retention, and caching](https://bkper.com/docs/ai/ai-gateway.md#privacy-retention-and-caching).
128
+ For more designs, see TypeSafe's [Patterns](https://docs.typesafe.ai/patterns) and [Cookbooks](https://docs.typesafe.ai/cookbooks).
280
129
 
281
130
  ## Common mistakes
282
131
 
283
- - **Sending Responses fields.** The body accepts only `model`, `state`, and `questions`. `input`, `stream`, `store`, `temperature`, and `metadata` are rejected.
284
- - **Putting the question in the ID.** The model never sees IDs. Write the full question in `instructions`.
285
- - **Asking for analysis.** Ask one snap judgment per question and combine answers in code.
132
+ - **Asking for analysis.** Ask one snap judgment per question and combine the answers in code.
286
133
  - **Asking the model to calculate.** Match amounts, compute date windows, and check balances in code.
287
- - **Treating `noul` as a boolean or `score` as an integer.** Both are continuous. Compare them with thresholds.
288
- - **Expecting an explanation.** Decision models return no text. Use a [language model](https://bkper.com/docs/ai/ai-gateway.md) when you need one.
134
+ - **Putting the question in its name.** The model never sees question IDs. Write the full question in its instructions.
135
+ - **Treating answers as verdicts.** A probability of yes is not a boolean, and a score can fall between levels. Compare both with thresholds.
136
+ - **Expecting an explanation.** Decision models return no text. Use a [language model](https://bkper.com/docs/ai/models.md) when you need one.
137
+ - **Sending a language-model request.** A decision request carries only the model, the facts, and the questions. See the [request rules](https://bkper.com/docs/api/ai-gateway.md#decision-request).
289
138
 
290
139
  ## Jev by TypeSafe
291
140
 
292
141
  [Jev](https://docs.typesafe.ai/introduction) is TypeSafe's flagship model and the first System One model. Its Bkper model ID is `jev`.
293
142
 
294
- - **Versions.** `jev-latest` and versioned IDs are accepted but always select the current Jev; you cannot pin a version. Log the returned `model`, and re-check tuned thresholds when it changes.
143
+ - **Versions.** `jev-latest` and versioned IDs are accepted but always select the current Jev; you cannot pin a version. Log the revision each answer reports, and re-check tuned thresholds when it changes.
295
144
  - **Input.** Text only. English is Jev's primary training language; other languages work with lower accuracy.
296
145
  - **Known weak spots.** Literal reading, arithmetic, date comparison, and large states full of irrelevant detail. See [Jev 1.13 jaggedness](https://docs.typesafe.ai/model-jaggedness/jev-1.13).
297
146
 
298
- ### Differences from the TypeSafe API
299
-
300
- Request and answer shapes match TypeSafe's [`POST /v1/systemone`](https://docs.typesafe.ai/api), so TypeSafe's guidance on questions, state, confidence, and patterns applies unchanged. Only the surroundings differ:
301
-
302
- - **Endpoint and authentication.** Call `https://ai.bkper.app/v1/decisions` with a Bkper access token. TypeSafe API keys do not work here.
303
- - **SDKs.** TypeSafe SDKs work with base URL `https://ai.bkper.app` and a Bkper access token. See [Call from code](#call-from-code).
304
- - **Errors.** Bkper returns `400` where TypeSafe returns `422`, and `503` with `provider_overloaded` where TypeSafe returns `529`. A `429` can also mean your Bkper AI allowance is exhausted.
305
- - **Usage.** Requests count against your [Bkper AI allowance](https://bkper.com/docs/ai/models.md#how-usage-works), not a TypeSafe account.
306
-
307
- ### Build with a coding agent
308
-
309
- TypeSafe's [agent skill](https://docs.typesafe.ai/agent-skill) gives coding agents context on questions and patterns. When you use it for a Bkper integration, point the agent to this page — `https://bkper.com/docs/ai/decision-models.md` — for the endpoint, authentication, model ID, and errors.
147
+ Requests count against your Bkper AI allowance at Jev's [usage rates](https://bkper.com/docs/ai/models.md#usage-rates).
310
148
 
311
- ## Learn more
149
+ ## Build it
312
150
 
313
- - [`createDecision` API reference](https://bkper.com/docs/api/ai/operations/createdecision.md) — the field-by-field contract.
314
- - [Models and Usage](https://bkper.com/docs/ai/models.md) — decision models, limits, and usage rates.
315
- - [Bkper AI Gateway](https://bkper.com/docs/ai/ai-gateway.md) — access, tokens, and privacy.
316
- - [Add Bkper AI to an App](https://bkper.com/docs/platform/apps/ai.md) — TypeSafe SDK setup for apps and scripts.
317
- - TypeSafe: [System One](https://docs.typesafe.ai/concepts/system-one), [AI primer](https://docs.typesafe.ai/introduction/machine-learning-primer), [Primitives](https://docs.typesafe.ai/primitives), [State](https://docs.typesafe.ai/concepts/state), [Confidence](https://docs.typesafe.ai/confidence), and [Patterns](https://docs.typesafe.ai/patterns).
151
+ - [Add Bkper AI to an App](https://bkper.com/docs/platform/apps/ai.md#ask-a-decision-model) — ask a decision model from an app Worker, a script, or a browser with TypeSafe's SDK.
152
+ - [AI Gateway API: decision models](https://bkper.com/docs/api/ai-gateway.md#decision-models) — the request, answer guarantees, errors, caching, and compatibility with TypeSafe.
153
+ - [`createDecision` reference](https://bkper.com/docs/api/ai-gateway/operations/createdecision.md) — every field.
154
+ - [Models and Usage](https://bkper.com/docs/ai/models.md) — usage rates, the allowance, and privacy.
155
+ - Building with a coding agent? Point it to this page for design, and to `https://bkper.com/docs/api/ai-gateway.md` for the endpoint, authentication, and errors. TypeSafe's [agent skill](https://docs.typesafe.ai/agent-skill) adds questions and patterns.
156
+ - TypeSafe: [System One](https://docs.typesafe.ai/concepts/system-one), [How to build with System One](https://docs.typesafe.ai/concepts/how-to-build-with-system-one), [AI primer](https://docs.typesafe.ai/introduction/machine-learning-primer), [Primitives](https://docs.typesafe.ai/primitives), [State](https://docs.typesafe.ai/concepts/state), [Confidence](https://docs.typesafe.ai/confidence), and [Patterns](https://docs.typesafe.ai/patterns).
157
+ - [Back to AI overview](https://bkper.com/docs/ai.md).