@abloatai/ablo 0.37.0 → 0.38.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.
package/AGENTS.md CHANGED
@@ -13,10 +13,10 @@ Don't hand-write the integration. Run the CLI; it generates the current-API sche
13
13
  - **Auth:** set `ABLO_API_KEY` in the environment. Do **NOT** run `ablo login` — it opens a browser device flow and blocks an agent.
14
14
  - **Connect your database — logical replication (the primary path):** `npx ablo connect` prints the setup SQL (`wal_level=logical`, a publication, a `REPLICATION` role); `npx ablo connect register` registers the source with Ablo in one step. Ablo **consumes your Postgres' logical-replication stream** — it never runs DDL on, writes to, owns, or migrates your database, and your application keeps the write path. Registration **is** the enable; there is no tier or flag to pick. (Ablo hosts only the transaction log + coordination, never your rows.)
15
15
  - **Fallback — signed Data Source endpoint** (DB can't grant a `REPLICATION` role): the generated `ablo/data-source.ts` exposes one route; Ablo sends signed requests and your app touches its own DB. **Only in this mode** does `npx ablo migrate` provision the adapter's bookkeeping tables (`ablo_outbox`, `ablo_idempotency`) plus your Ablo models — it does **not** touch your other tables. Keep your own migrations (drizzle-kit / prisma migrate) for auth and anything outside the Ablo schema.
16
- - **No database yet?** A sandbox `sk_test` key holds throwaway **test data** (Stripe-test-mode style) so you can try Ablo before connecting your own Postgres. Test-mode only in production every row lives in your database.
16
+ - **No database yet?** Run `npx ablo dev --no-watch --branch <name>` to create an isolated non-root branch and obtain its expiring `sk_test_` credential. The branch uses a throwaway hosted data plane; Production remains the protected root. There is no shared Sandbox mode.
17
17
  - **Adopt an existing DB schema:** `npx ablo pull prisma [path]` / `pull drizzle <module>` (lossless) or `pull` (live DB, lossy). Writes `ablo/schema.ts`.
18
- - **Push your schema — REQUIRED before any write works.** The server keeps its OWN copy of the schema. After you create or edit `ablo/schema.ts`, run `npx ablo push` (one-shot) or `npx ablo dev --no-watch`. **Skip this and every write to a new or changed model fails with `server_execute_unknown_model`.** (Plain `ablo dev` watches forever — never run it bare in an agent.)
19
- - **Other long-running:** `npx ablo logs --no-follow` (default tails forever). `npx ablo mode test|live` ALWAYS pass the argument. `status`, `push`, `pull`, `check`, `generate`, `docs` are one-shot — safe as-is.
18
+ - **Prepare a branch and push your schema — REQUIRED before any write works.** The server keeps its OWN copy of the schema. After you create or edit `ablo/schema.ts`, run `npx ablo dev --no-watch --branch <git-or-ci-ref>`: it ensures an isolated branch, mints a temporary branch credential, writes it to gitignored `.env.local`, pushes once, and exits. **Skip this and every write to a new or changed model fails with `server_execute_unknown_model`.** Plain `ablo dev` watches forever — never run it bare in an agent. `ablo push` is the lower-level one-shot command for an already selected key, including reviewed production deploys.
19
+ - **Other long-running:** `npx ablo logs --no-follow` (default tails forever). `status`, `branch check`, `push`, `pull`, `check`, `generate`, `docs`, and `dev --no-watch` are one-shot.
20
20
 
21
21
  When you use the signed-endpoint fallback, the generated `ablo/data-source.ts` is the whole endpoint and needs no hand-editing: `dataSourceNext({ schema, apiKey, adapter: prismaDataSource(prisma, schema) })` (or `drizzleDataSource(db, schema)`). The adapter owns commit / idempotency / outbox.
22
22
 
package/CHANGELOG.md CHANGED
@@ -1,96 +1,166 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.38.0
4
+
5
+ ### Branch-isolated development
6
+
7
+ Ablo branches replace the former shared Sandbox mode. Every project has a
8
+ protected Production root and can have multiple isolated development, preview,
9
+ test, or long-lived branches. Credentials are bound to immutable branch
10
+ identities, so changing a slug or request parameter cannot redirect a write.
11
+
12
+ `npx ablo dev` now discovers the current Git or CI branch, ensures the matching
13
+ Ablo branch, mints an expiring branch credential, writes it to the gitignored
14
+ local environment, pushes the schema, and watches for changes. Use
15
+ `npx ablo dev --no-watch --branch <name>` for a one-shot agent or CI setup.
16
+
17
+ The CLI also provides `ablo branch list`, `create`, `ensure`, `status`, `check`,
18
+ `credential`, and `delete`. The public HTTP and OpenAPI contracts expose the
19
+ same lifecycle for other languages and deployment systems.
20
+
21
+ This release removes the CLI mode switch and the dashboard Sandbox surface.
22
+ Production remains the protected root; a development credential cannot select
23
+ another branch or gain production authority.
24
+
25
+ Source adapters and PostgreSQL footprint helpers now select immutable branches.
26
+ If you construct `FootprintPlane` or `SourceRequestContext`, replace
27
+ `environment`, `mode`, and `sandboxId` with `branchId`.
28
+
29
+ ### Temporal and Inngest integration guides
30
+
31
+ New runnable examples and documentation show how Temporal and Inngest
32
+ workflows use Ablo without introducing another authority path. Temporal
33
+ activities and Inngest steps create the Ablo client, perform authoritative
34
+ reads, acquire claims for long-running work, and submit idempotent writes
35
+ through the same transaction API as every other caller.
36
+
37
+ The integrations keep each product in its proper role: Temporal and Inngest
38
+ own durable execution, scheduling, retries, and workflow history; Ablo owns
39
+ shared-data authority, claims, conflicts, idempotency, settlement, and ordered
40
+ observation. Workflow code does not open WebSockets or hold live client state.
41
+
42
+ ### Database adapter foundation, starting with PostgreSQL
43
+
44
+ Customer-database adapters now declare their database, ORM binding, and
45
+ observation strategy as separate axes. The existing Prisma, Drizzle, and Kysely
46
+ integrations are accurately identified as PostgreSQL bindings using either a
47
+ transactional outbox or PostgreSQL WAL.
48
+
49
+ All built-in adapters are constructed through one validating factory and the
50
+ shared conformance suite checks that the three axes are present. Impossible
51
+ capability combinations fail during adapter construction instead of silently
52
+ advertising guarantees the database path cannot provide.
53
+
54
+ PostgreSQL is the first database profile on this axis. The contract leaves room
55
+ for additional databases without pretending their transaction, observation,
56
+ and change-capture guarantees are interchangeable with PostgreSQL.
57
+
58
+ ### Generated language SDK foundation
59
+
60
+ The HTTP API is now explicitly treated as Ablo's language-neutral product
61
+ boundary. Its OpenAPI artifact follows the current Ablo version and every
62
+ operation has a stable, unique name suitable for deterministic Python and Go
63
+ generation.
64
+
65
+ The OpenAPI generator and drift check are restored as repository and CI gates.
66
+ Future language clients will generate their transport, wire models, and error
67
+ decoding from this contract, retaining handwritten code only for thin
68
+ language-idiomatic resource and claim façades.
69
+
70
+ The artifact now names shared claim, receipt, cursor, page, and error schemas;
71
+ references the canonical error envelope from every operation; publishes typed
72
+ pagination parameters and explicit union discriminators; and normalizes Zod's
73
+ JSON Schema output to the portable subset accepted by the Python and Go
74
+ generator candidates. CI also validates the rendered OpenAPI 3.1 document with
75
+ an independent, pinned Redocly CLI.
76
+
77
+ ### AI SDK tools over the transaction API
78
+
79
+ `@abloatai/ablo/ai-sdk` now exposes small tool adapters for authoritative
80
+ reads, idempotent creates, concurrency-safe updates, and claimed deletes. These
81
+ helpers use the caller's existing typed Ablo model resource; they do not add an
82
+ agent runtime or a second transport.
83
+
84
+ The public surface follows the model verbs directly: `readTool`, `createTool`,
85
+ `updateTool`, and `deleteTool`. AI SDK metadata and approval policy pass through
86
+ to each tool, destructive tools require approval by default, and cancellation
87
+ stops queued claim acquisition.
88
+
89
+ This deliberately replaces the previously published `coordinatedTool` naming:
90
+ use `updateTool`, `UpdateToolModel`, `UpdateToolOptions`, `UpdateToolResult`,
91
+ `UpdateStrategy`, and the `status` result field. The former
92
+ `coordinatedTool`, `CoordinatedModel`, `CoordinatedToolOptions`,
93
+ `CoordinatedWriteResult`, and `CoordinationStrategy` exports are removed rather
94
+ than retained as legacy aliases.
95
+
96
+ Queued tool writes now use Ablo's server-owned FIFO claim queue rather than
97
+ recreating coordination with client-side polling.
98
+
99
+ Internal job dispatch, concrete worker tools, prompts, sandboxes, and model
100
+ selection remain application concerns and are not part of the public Ablo
101
+ agent surface.
102
+
103
+ ## 0.37.1
104
+
105
+ ### A clearer introduction to Ablo
106
+
107
+ The package README now explains Ablo from the problem outward: humans already
108
+ coordinate shared work by seeing who is active, agreeing on ownership, waiting,
109
+ and looking again before continuing; Ablo gives agents those same practical
110
+ capabilities in software.
111
+
112
+ It also makes the headless product explicit. The TypeScript SDK is backed by a
113
+ pure HTTP transaction API, so agents, services, jobs, command-line tools, and
114
+ interactive applications can use the same coordination model without requiring
115
+ a browser or reactive client.
116
+
117
+ ### Lower overhead on busy write paths
118
+
119
+ Large create batches now return only the inserted identifiers needed for
120
+ idempotency handling instead of sending every inserted column back to the
121
+ server. Live clients also bypass reconciliation work when a publication frame
122
+ contains one change per entity.
123
+
124
+ These changes reduce server response volume and client materialization work.
125
+ There are no public API changes in 0.37.1.
126
+
3
127
  ## 0.37.0
4
128
 
5
- ### Minor Changes
6
-
7
- - f60ed16: Harden browser authentication around one typed credential endpoint contract,
8
- full-plane persistence isolation, awaited terminal cleanup, actual credential
9
- expiry, and least-privilege human sessions.
10
-
11
- Human session minting now requires a non-empty schema-typed `can` grant. It
12
- accepts concrete model operations and has no all-data wildcard. Browser
13
- credentials remain short-lived, refreshable, and isolated from long-lived
14
- server secrets.
15
-
16
- Endpoint URLs move from `apiKey` to `authEndpoint`. The canonical session and
17
- capability mint routes are `/v1/ephemeral_keys` and `/v1/capabilities`; legacy
18
- route aliases are removed.
19
-
20
- Credential providers now use the `CredentialProvider` type. The former
21
- `ApiKeySetter` export is removed.
22
-
23
- - 16cc7d1: Claims are field-granular. The `path` and `range` claim targets are removed, and
24
- a claim narrows to a whole field or set of fields and no finer. Two agents on the
25
- same row proceed concurrently when they hold different fields, and serialize when
26
- they share one.
27
-
28
- This is a breaking removal (the `path` and `range` claim options, the
29
- `TargetRange` type, and sub-field conflict semantics are gone) and a deliberate
30
- one. A claim must not promise finer exclusion than the write path can deliver,
31
- and the smallest thing a write addresses is a whole field: nothing writes part of
32
- a value. `path`/`range` let two writers hold disjoint spans of one field and told
33
- them it was safe, which it is not until concurrent edits to one field can be
34
- reconciled (operational transformation). Until that lands, field is the floor;
35
- when it lands, sub-field targets return, working.
36
-
37
- If you narrowed a claim by `path` or `range`, claim the field the position lives
38
- in instead: `fields: ['content']`. To describe a sub-field region to peers for
39
- display, put it in `meta` that promises nothing about exclusion.
40
-
41
- - 08a3cad: Launch the branded Ablo package as the single package application developers
42
- install. The root serves headless HTTP callers, while `/client` and `/react`
43
- serve WebSocket-backed reactive applications.
44
-
45
- The public surface now provides:
46
-
47
- - `@abloatai/ablo` for agents, services, workers, jobs, and backend code;
48
- - `@abloatai/ablo/client` for live local state;
49
- - `@abloatai/ablo/react` for React bindings;
50
- - branded schema, source-adapter, server, authorization, coordination, and wire
51
- subpaths; and
52
- - `/source/next`, `/source/drizzle`, `/source/kysely`, and
53
- `/source/conformance` for Data Source integrations.
54
-
55
- Authoritative reads use `model.get({ id })`; reactive snapshots use
56
- `model.local.get(id)`.
57
-
58
- Ablo is now presented as the transaction and coordination API for state
59
- operated by humans, services, tools, and AI agents. Realtime synchronization
60
- remains available as a client capability rather than defining the product.
61
- Live applications no longer accept HTTP transport configuration, and the old
62
- sync-engine package and compatibility paths are removed.
63
-
64
- The public repository preserves the workspace structure used for development
65
- instead of flattening sources into a generated package. The branded banner,
66
- documentation, examples, license, notices, and release automation remain part
67
- of the repository.
68
-
69
- The new package pages direct application developers to the branded Ablo
70
- entrypoints while still documenting where integration authors can find the
71
- lower-level transaction and interactive-client contracts.
72
-
73
- - f60ed16: Improve confirmed commit throughput and live-client materialization without
74
- weakening atomic writes, ordered observation, audit delivery, or replay.
75
-
76
- The certified AWS benchmark sustained more than 10,000 committed operations per
77
- second for homogeneous creates, mixed creates, updates, and deletes with zero
78
- write errors and sub-second publication drain. The result covers the documented
79
- single-plane, 12-client, 500-operation benchmark topology rather than claiming
80
- universal production capacity.
81
-
82
- Live clients now defer reactive model activation until state reaches a
83
- consumer-visible boundary and keep cache eviction work bounded under sustained
84
- ingestion. Optimistic state and actively observed models remain immediately
85
- reactive.
86
-
87
- ### Patch Changes
88
-
89
- - Updated dependencies [f60ed16]
90
- - Updated dependencies [16cc7d1]
91
- - Updated dependencies [08a3cad]
92
- - Updated dependencies [f60ed16]
93
- - @abloatai/transaction@0.37.0
94
- - @abloatai/humans@0.37.0
95
-
96
- Release notes are generated from the repository changesets.
129
+ ### One Ablo SDK for humans, agents, and backend systems
130
+
131
+ Ablo is now presented and shipped as the transaction and coordination layer for
132
+ shared application state—not only as a realtime synchronization library.
133
+
134
+ Install `@abloatai/ablo` as the single public SDK:
135
+
136
+ - `@abloatai/ablo` provides the pure HTTP path for agents, services, workers,
137
+ jobs, server actions, and other headless runtimes.
138
+ - `@abloatai/ablo/client` adds live local state, optimistic interaction,
139
+ persistence, and presence for human-facing applications.
140
+ - `@abloatai/ablo/react` provides the React bindings.
141
+
142
+ Every entrypoint uses the same schema, capabilities, commits, claims,
143
+ idempotency, settlement, and ordered changes. Authoritative reads use
144
+ `model.get({ id })`; local reactive snapshots use `model.local.get(id)`.
145
+
146
+ ### Coordination now matches the unit applications can safely write
147
+
148
+ Claims can coordinate an entire row or a typed set of fields. Two actors
149
+ working on different fields of the same row can proceed concurrently, while
150
+ overlapping work takes turns.
151
+
152
+ Sub-field `path` and `range` claims have been removed because the write path
153
+ cannot yet guarantee independent updates within one field. Applications using
154
+ those options should claim the containing field instead and keep any
155
+ cursor/range information in claim metadata for display.
156
+
157
+ ### Safer authority for browser applications
158
+
159
+ Browser sessions now use one typed, short-lived credential flow and require a
160
+ non-empty schema-typed `can` grant. Applications specify the exact model
161
+ operations a session may perform instead of issuing ambient all-data access.
162
+
163
+ Use `authEndpoint` for the browser credential endpoint. The supported routes
164
+ are `/v1/ephemeral_keys` and `/v1/capabilities`; the former `apiKey` endpoint
165
+ option and legacy route aliases are removed. Credential callbacks now use the
166
+ `CredentialProvider` type.
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  </p>
4
4
 
5
5
  <p align="center">
6
- <strong>Transaction and coordination infrastructure for humans, agents, and backend systems.</strong>
6
+ <strong>The transaction layer for AI agents.</strong>
7
7
  </p>
8
8
 
9
9
  <p align="center">
@@ -22,45 +22,110 @@
22
22
 
23
23
  ---
24
24
 
25
- Install the public SDK:
25
+ Safely coordinate AI agents, humans, workflows, and services writing to the
26
+ same database.
27
+
28
+ Ablo is an authoritative transaction layer for shared application state. Every
29
+ write goes through one typed API where authority, idempotency, conflicts,
30
+ ordering, and confirmation can be enforced. Your Postgres remains the source
31
+ of truth.
32
+
33
+ ## Why Ablo
34
+
35
+ Software used to have one writer: a human clicking through an application. AI
36
+ applications now have humans, agents, workflows, and services acting
37
+ concurrently. Databases keep transactions consistent. They do not coordinate
38
+ autonomous work that reads now, reasons for thirty seconds, and writes later.
39
+
40
+ Humans handle this naturally. We see that somebody is editing, agree on who
41
+ takes which part, wait our turn, and look again before continuing. Ablo gives
42
+ software actors those same capabilities: bounded authority, shared ownership,
43
+ fresh context, safe handoffs, and an attributed record of what happened.
44
+
45
+ ## Start
26
46
 
27
47
  ```sh
28
48
  npm install @abloatai/ablo
49
+ npx ablo init
50
+ npx ablo dev
29
51
  ```
30
52
 
31
- Use the root package for headless agents, services, jobs, and backend code:
53
+ `ablo dev` prepares an isolated Ablo branch for your Git branch, writes its
54
+ temporary credential to gitignored `.env.local`, pushes the schema, and watches
55
+ for changes.
56
+
57
+ Read and write through the transaction layer:
32
58
 
33
59
  ```ts
34
- import { Ablo } from '@abloatai/ablo';
60
+ const order = await ablo.orders.get({ id: orderId });
35
61
 
36
- const ablo = Ablo({ schema, apiKey: process.env.ABLO_API_KEY });
62
+ if (!order) throw new Error('Order not found');
37
63
  await ablo.orders.update({
38
- id: orderId,
64
+ id: order.id,
39
65
  data: { status: 'approved' },
66
+ wait: 'confirmed',
40
67
  });
41
68
  ```
42
69
 
43
- Use the client entrypoint for a WebSocket-backed reactive application:
70
+ `confirmed` means the authoritative database reported the change back. The
71
+ same commit can be retried safely if the caller loses its connection.
72
+
73
+ When work takes thirty seconds instead of one request, coordinate before the
74
+ agent starts reasoning:
44
75
 
45
76
  ```ts
46
- import { Ablo } from '@abloatai/ablo/client';
77
+ await using claim = await ablo.orders.claim({ id: orderId });
78
+
79
+ const priced = await pricingAgent(claim.data);
47
80
 
48
- const ablo = Ablo({ schema, authEndpoint: '/api/ablo-session' });
49
- await ablo.ready();
81
+ await ablo.orders.update({
82
+ id: claim.data.id,
83
+ data: { total: priced.total, status: 'repriced' },
84
+ claim,
85
+ wait: 'confirmed',
86
+ });
50
87
  ```
51
88
 
52
- React bindings are available from `@abloatai/ablo/react`.
89
+ Another actor touching the same work waits fairly and receives fresh state when
90
+ its turn begins. If the agent fails, the claim releases automatically. If its
91
+ context became stale, the write is rejected instead of silently overwriting
92
+ work it never saw.
53
93
 
54
- The repository keeps implementation ownership explicit:
94
+ If you use AI SDK, expose the same operation as a typed model tool:
55
95
 
56
- ```text
57
- packages/ablo branded SDK users install
58
- packages/transaction HTTP, contracts, commits, claims, settlement, observation
59
- packages/humans WebSocket, local materialization, presence, MobX, React
60
- packages/agent agent behavior and perception
61
- packages/cli project and operational tooling
96
+ ```ts
97
+ import { updateTool } from '@abloatai/ablo/ai-sdk';
98
+
99
+ const approveOrder = updateTool(ablo.orders, {
100
+ description: 'Approve an order after reviewing it.',
101
+ inputSchema: z.object({ orderId: z.string() }),
102
+ id: ({ orderId }) => orderId,
103
+ apply: () => ({ status: 'approved' }),
104
+ });
62
105
  ```
63
106
 
64
- Realtime synchronization is a consumer of the transaction layer, not a second
65
- authority path. Humans, agents, and backend services use the same commit,
66
- idempotency, claim, fencing, settlement, and ordered-observation contracts.
107
+ Ablo supplies `readTool`, `createTool`, `updateTool`, and `deleteTool` over the
108
+ same authoritative resources. AI SDK keeps ownership of the model loop and tool
109
+ execution.
110
+
111
+ Use `@abloatai/ablo` for agents and backend code,
112
+ `@abloatai/ablo/client` for live applications, and
113
+ `@abloatai/ablo/react` for React. All entrypoints share the same schema,
114
+ authority, commits, claims, and ordered changes.
115
+
116
+ Read the [Quickstart](https://docs.abloatai.com/quickstart), browse
117
+ [docs.abloatai.com](https://docs.abloatai.com), or run `npx ablo docs`.
118
+
119
+ ## Contributing
120
+
121
+ Ablo is free and open source. You can help by
122
+ [opening an issue](https://github.com/Abloatai/ablo/issues),
123
+ [suggesting a feature](https://github.com/Abloatai/ablo/issues/new), or
124
+ [contributing code](https://github.com/Abloatai/ablo/pulls).
125
+
126
+ Please report vulnerabilities privately through
127
+ [GitHub Security Advisories](https://github.com/Abloatai/ablo/security/advisories/new).
128
+
129
+ ## License
130
+
131
+ Apache License 2.0. See [LICENSE](./LICENSE) and [NOTICE](./NOTICE).
@@ -0,0 +1,2 @@
1
+ export * from '@abloatai/transaction/ai-sdk';
2
+ //# sourceMappingURL=ai-sdk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-sdk.d.ts","sourceRoot":"","sources":["../src/ai-sdk.ts"],"names":[],"mappings":"AAAA,cAAc,8BAA8B,CAAC"}
package/dist/ai-sdk.js ADDED
@@ -0,0 +1,2 @@
1
+ export * from '@abloatai/transaction/ai-sdk';
2
+ //# sourceMappingURL=ai-sdk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-sdk.js","sourceRoot":"","sources":["../src/ai-sdk.ts"],"names":[],"mappings":"AAAA,cAAc,8BAA8B,CAAC"}
package/docs/agents.md CHANGED
@@ -6,7 +6,7 @@ An agent is a **reactive** participant: it wakes on something happening, reads
6
6
  what it needs, writes a result, and goes idle. That's a request/response
7
7
  workload — so agents talk to Ablo over **plain HTTP**, holding no WebSocket. The
8
8
  credential *is* the identity; the server resolves the org, scope, and actor from
9
- the key on every request (the Stripe server-SDK / Liveblocks-node shape).
9
+ the key on every request.
10
10
 
11
11
  Agents get the stateless plane (HTTP). People — when you add the `humans()`
12
12
  plugin — get the live plane (WebSocket: presence, optimistic, sub-100ms).
@@ -31,7 +31,7 @@ import { schema } from "./schema";
31
31
  const ablo = Ablo({ schema, apiKey: process.env.ABLO_API_KEY, transport: "http" });
32
32
 
33
33
  // Reads + writes, fully typed off your schema.
34
- // `retrieve` resolves to the row, or `undefined` when none matches.
34
+ // `get` resolves to the row, or `undefined` when none matches.
35
35
  const open = await ablo.tasks.list({ where: { status: "todo" } });
36
36
 
37
37
  const task = await ablo.tasks.get({ id: open[0].id });
@@ -41,11 +41,57 @@ console.log(task.title);
41
41
  await ablo.tasks.update({ id: task.id, data: { status: "done" } });
42
42
  ```
43
43
 
44
- It exposes `retrieve` / `list` / `create` / `update` / `delete`, plus `commits`
45
- and `claim`. It does **not** expose the stateful-only surface (`get` /
46
- `local` reads, `onChange` live subscription) those need a
47
- live connection, so with `transport: 'http'` the return type narrows and they
48
- are a *compile error*, not a runtime surprise.
44
+ It exposes `get` / `list` / `create` / `update` / `delete`, plus `commits`
45
+ and `claim`. It does **not** expose stateful-only `local` reads or `onChange`
46
+ subscriptions. Those need a live connection, so with `transport: 'http'` they
47
+ are compile errors rather than runtime surprises.
48
+
49
+ ## AI SDK tools
50
+
51
+ Keep AI SDK in charge of the model loop and expose only the Ablo operations the
52
+ model needs:
53
+
54
+ ```ts
55
+ import { generateText } from 'ai';
56
+ import {
57
+ createTool,
58
+ deleteTool,
59
+ readTool,
60
+ updateTool,
61
+ } from '@abloatai/ablo/ai-sdk';
62
+
63
+ const tools = {
64
+ getTask: readTool(ablo.tasks, {
65
+ description: 'Read the current task.',
66
+ inputSchema: z.object({ taskId: z.string() }),
67
+ id: ({ taskId }) => taskId,
68
+ }),
69
+ createTask: createTool(ablo.tasks, {
70
+ description: 'Create a task.',
71
+ inputSchema: z.object({ requestId: z.string(), title: z.string() }),
72
+ id: ({ requestId }) => requestId,
73
+ data: ({ title }) => ({ title, status: 'todo' }),
74
+ }),
75
+ updateTask: updateTool(ablo.tasks, {
76
+ description: 'Update a task without overwriting concurrent work.',
77
+ inputSchema: z.object({ taskId: z.string(), status: z.string() }),
78
+ id: ({ taskId }) => taskId,
79
+ apply: (_current, { status }) => ({ status }),
80
+ }),
81
+ deleteTask: deleteTool(ablo.tasks, {
82
+ description: 'Delete a task after taking its claim.',
83
+ inputSchema: z.object({ taskId: z.string() }),
84
+ id: ({ taskId }) => taskId,
85
+ // Destructive tools require AI SDK approval by default.
86
+ }),
87
+ };
88
+
89
+ await generateText({ model, messages, tools });
90
+ ```
91
+
92
+ These are adapters over the same typed resources used by ordinary backend
93
+ code. Ablo does not own the planner, prompt system, memory, provider, worker,
94
+ or workflow runtime.
49
95
 
50
96
  ## Coordination: claim, queue, reorder
51
97
 
@@ -59,7 +105,11 @@ clobber the same record.
59
105
  await using claim = await ablo.tasks.claim({ id: taskId });
60
106
  const task = claim.data;
61
107
  // …no one else can hold this row while you work…
62
- await ablo.tasks.update({ id: task.id, data: { status: "in_review" } });
108
+ await ablo.tasks.update({
109
+ id: task.id,
110
+ data: { status: "in_review" },
111
+ claim,
112
+ });
63
113
 
64
114
  await ablo.tasks.claim.state({ id: taskId }); // who holds it now (or null)
65
115
  await ablo.tasks.claim.queue({ id: taskId }); // the FIFO wait-line behind the holder
@@ -111,5 +161,5 @@ agents costs nothing on the live plane — that capacity stays for humans.
111
161
  `onChange` (live subscriptions) and the `local` reads (local synced-pool
112
162
  reads) require a WebSocket and a local store — they're for interactive UIs, not
113
163
  stateless agents. An agent reacts to an external trigger (a job/queue/webhook),
114
- then reads with `list`/`retrieve`. See [client behavior](/client-behavior) for
164
+ then reads with `list`/`get`. See [client behavior](/client-behavior) for
115
165
  the full surface and [guarantees](/guarantees) for the coordination semantics.