10xgraph-client 1.0.0-rc.2 → 1.0.0-rc.3

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.
Files changed (53) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +169 -225
  3. package/dist/cjs/client.d.ts +55 -19
  4. package/dist/cjs/endpoints/forgetMemories.d.ts +3 -1
  5. package/dist/cjs/endpoints/listMemories.d.ts +3 -0
  6. package/dist/cjs/endpoints/me.d.ts +25 -0
  7. package/dist/cjs/endpoints/searchMemory.d.ts +3 -1
  8. package/dist/cjs/endpoints/tasks.d.ts +95 -0
  9. package/dist/cjs/endpoints/threads.d.ts +3 -0
  10. package/dist/cjs/filters.d.ts +27 -0
  11. package/dist/cjs/index.d.ts +3 -1
  12. package/dist/cjs/message.d.ts +3 -0
  13. package/dist/client.d.ts +55 -19
  14. package/dist/client.d.ts.map +1 -1
  15. package/dist/endpoints/forgetMemories.d.ts +3 -1
  16. package/dist/endpoints/forgetMemories.d.ts.map +1 -1
  17. package/dist/endpoints/listMemories.d.ts +3 -0
  18. package/dist/endpoints/listMemories.d.ts.map +1 -1
  19. package/dist/endpoints/me.d.ts +26 -0
  20. package/dist/endpoints/me.d.ts.map +1 -0
  21. package/dist/endpoints/searchMemory.d.ts +3 -1
  22. package/dist/endpoints/searchMemory.d.ts.map +1 -1
  23. package/dist/endpoints/tasks.d.ts +96 -0
  24. package/dist/endpoints/tasks.d.ts.map +1 -0
  25. package/dist/endpoints/threads.d.ts +3 -0
  26. package/dist/endpoints/threads.d.ts.map +1 -1
  27. package/dist/filters.d.ts +28 -0
  28. package/dist/filters.d.ts.map +1 -0
  29. package/dist/index.cjs +3 -3
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.d.ts +3 -1
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +1217 -1122
  34. package/dist/index.js.map +1 -1
  35. package/dist/message.d.ts +3 -0
  36. package/dist/message.d.ts.map +1 -1
  37. package/dist/tools.d.ts.map +1 -1
  38. package/package.json +2 -2
  39. package/src/client.ts +107 -42
  40. package/src/endpoints/forgetMemories.ts +10 -2
  41. package/src/endpoints/listMemories.ts +6 -0
  42. package/src/endpoints/me.ts +71 -0
  43. package/src/endpoints/searchMemory.ts +3 -1
  44. package/src/endpoints/tasks.ts +170 -0
  45. package/src/endpoints/threads.ts +10 -0
  46. package/src/filters.ts +32 -0
  47. package/src/index.ts +9 -1
  48. package/src/message.ts +4 -0
  49. package/src/tools.ts +13 -5
  50. package/dist/cjs/endpoints/addThreadMessages.d.ts +0 -25
  51. package/dist/endpoints/addThreadMessages.d.ts +0 -26
  52. package/dist/endpoints/addThreadMessages.d.ts.map +0 -1
  53. package/src/endpoints/addThreadMessages.ts +0 -88
package/CHANGELOG.md CHANGED
@@ -26,6 +26,45 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
26
26
 
27
27
  ---
28
28
 
29
+ ## [1.0.0-rc.3] - 2026-11-11
30
+
31
+ The third release candidate of `10xgraph-client` 1.0. Use it with `10xgraph-api` 1.0.0rc6. New
32
+ response fields are typed optional, so the client still works against older servers; a
33
+ `ToolResultBlock.name` sent to an older server is ignored there.
34
+
35
+ ### Added
36
+
37
+ - `ToolResultBlock.name?: string`: the name of the tool that produced the result. The server sets it on results from `10xgraph` 1.0.0rc6 or later; older results have none. Results the client builds for client-side tools (`ToolExecutor`: success, thrown error, unknown tool, rejected arguments, duplicate call id) set it too.
38
+ - `me()` for `GET /v1/me` of `10xgraph-api`: who the caller is and what they may do. `data` is
39
+ `{ user_id, tenant, roles, permissions, reach }` (`reach` is `own`, `tenant` or `all`; `permissions` is
40
+ `['*']` for an unrestricted identity) or `{ auth: 'off' }` when the server runs without auth. New exported
41
+ types and helper: `MeResponse`, `MeData`, `MeIdentity`, `MeAuthOff`, `MeReach`, `isAuthOff`. Needs a
42
+ `10xgraph-api` with RBAC.
43
+ - Background task methods for the `/v1/tasks` routes of `10xgraph-api`: `runTask(name, { args, kwargs })`,
44
+ `scheduleTask(name, { args, kwargs, schedule })`, `getTask(id)`, `rescheduleTask(scheduleId, schedule)`
45
+ and `cancelTask(id)`. `schedule` is exactly one of `{ cron }`, `{ at }` or `{ every }` (seconds); the
46
+ client does not validate it, the server answers 422. New exported types: `TaskStatus`, `TaskSchedule`,
47
+ `TaskRecord`, `ScheduleRecord`, `TaskCallOptions`, `RunTaskResponse`, `ScheduleTaskRequest`,
48
+ `ScheduleTaskResponse`, `GetTaskResponse`, `RescheduleTaskResponse`, `CancelTaskResponse`. Needs a
49
+ `10xgraph-api` with background tasks.
50
+ - Filter support. `threads()` takes `filters` (sent as a JSON `filters` query parameter);
51
+ `searchMemory()`, `listMemories()` and `forgetMemories()` take `filters` in the request body.
52
+ A filter is `{ column: value }` (equality) or `{ column: { op: value } }` with the operators
53
+ `eq`, `ne`, `in`, `nin`, `like`, `ilike`, `is_null`, `gt`, `gte`, `lt`, `lte`. New exported
54
+ types: `Filters`, `FilterCondition`, `FilterOperator`, `FilterScalar`. `listMemories()` gains
55
+ `filters`. The client does not validate columns; the server answers 422. Needs a `10xgraph-api`
56
+ with filter support.
57
+
58
+ ### Changed
59
+
60
+ - `forgetMemories()` now throws a `TenxGraphError` subclass on a failed request (`ValidationError`
61
+ for 422, with the server message) instead of a plain `Error`. When the response has no JSON
62
+ error body the message is still `Forget memories failed: <status> <statusText>`.
63
+
64
+ ### Removed
65
+
66
+ - `addThreadMessages` and its `AddThreadMessages*` types. The `POST /v1/threads/{thread_id}/messages` route was removed from `10xgraph-api`, so the method had nothing to call. Send messages through `invoke` or `stream`, and use `updateThreadMessageFeedback` for feedback.
67
+
29
68
  ## [1.0.0-rc.2] - 2026-10-30
30
69
 
31
70
  The second release candidate of `10xgraph-client` 1.0, aligned with `10xgraph` and `10xgraph-api`
package/README.md CHANGED
@@ -4,306 +4,240 @@
4
4
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
6
 
7
- The TypeScript client for the **10xGraph** API server. Build conversational AI applications with
8
- streaming responses, realtime audio, client-side tool execution, and dynamic state management.
7
+ The typed TypeScript client for 10xGraph, infrastructure for AI applications. It talks to the
8
+ `10xgraph-api` server from any frontend or Node app: invoke, stream, threads, memory, files,
9
+ background tasks, remote tools and realtime audio.
9
10
 
10
- 10xGraph by 10xScale: graph engineering for production AI agents.
11
+ > 10xGraph is open-source, self-hosted infrastructure for AI applications. You write the agents, tools and tasks; 10xGraph runs them behind an API server with authentication, role-based access, tenant isolation, durable state in Postgres and Redis, background jobs, metrics and tracing, and generates Docker and Kubernetes deploy files. MIT licensed, by 10xScale. Formerly Agentflow.
11
12
 
12
- > **Coming from `@10xscale/agentflow-client`?** This is the same client under its new name.
13
- > Change the import and you are done; the old `AgentFlow*` names still work until 2.0. See
13
+ > **Coming from `@10xscale/agentflow-client`?** This is the same client under its new name. Change
14
+ > the import and you are done; the old `AgentFlow*` names still work until 2.0. See
14
15
  > [Migrating from `@10xscale/agentflow-client`](#migrating-from-10xscaleagentflow-client).
15
16
 
16
- ## Features
17
-
18
- - **Simple API**: one client class with a method per server endpoint
19
- - **Streaming**: HTTP and WebSocket streaming for chat UIs
20
- - **Tool execution**: run browser-side tools locally, with recursion handling
21
- - **State management**: dynamic state schema with validation
22
- - **Realtime audio**: WebSocket audio-to-audio via `/v1/graph/live`
23
- - **TypeScript first**: full type definitions, dual ESM + CJS
24
-
25
- ## Installation
17
+ ## Install
26
18
 
27
19
  ```bash
28
20
  npm install 10xgraph-client
29
- # or
30
- yarn add 10xgraph-client
31
- # or
32
- pnpm add 10xgraph-client
21
+ # or: yarn add 10xgraph-client / pnpm add 10xgraph-client
33
22
  ```
34
23
 
35
- ### Version compatibility
36
-
37
- From 1.0, match `major.minor` across `10xgraph`, `10xgraph-api` and `10xgraph-client`; patch
38
- versions are independent (a patch is only a bug or security fix). Before 1.0, pick versions by
39
- this table:
40
-
41
- | `10xgraph-client` (npm) | API server | Core framework |
42
- | -------------------------------------- | ------------------------------------------------- | ------------------------------ |
43
- | 1.0.x | `10xgraph-api` 1.0.x | `10xgraph` 1.0.x |
44
- | 0.6.x | `10xgraph-api` >= 0.7.0 | `10xgraph` >= 0.10.0 |
45
- | `@10xscale/agentflow-client` 0.5.x | `10xscale-agentflow-cli` >= 0.6.0, `10xgraph-api` | `10xscale-agentflow` >= 0.10.0 |
46
- | `@10xscale/agentflow-client` 0.3-0.4.x | `10xscale-agentflow-cli` >= 0.5.0 | `10xscale-agentflow` >= 0.9.0 |
24
+ Node 20 or newer. It uses the global `fetch`, ships ESM and CJS with types, and works with any
25
+ frontend framework. There are no React hooks; call the client from your own state code.
47
26
 
48
- The client tracks the **API server**, which is what it talks to. Client 0.6.x and later authenticate
49
- WebSockets with the `10xgraph-bearer` subprotocol, which `10xgraph-api` 0.7.0 introduced. Against
50
- an older `10xscale-agentflow-cli` server, HTTP endpoints still work, but `wsStream()` and
51
- `realtime()` with bearer auth do not; stay on `@10xscale/agentflow-client@0.5.0` until the server
52
- is upgraded.
27
+ The client talks to a `10xgraph-api` server, so run one first. Match `major.minor` across
28
+ `10xgraph`, `10xgraph-api` and `10xgraph-client` (patch versions are independent). WebSocket auth
29
+ (`wsStream()` and `realtime()`) uses the `10xgraph-bearer` subprotocol, which needs `10xgraph-api`
30
+ 1.0. See [Run the server](https://10xgraph.com/docs/server/run-the-server).
53
31
 
54
- ## Quick Start
55
-
56
- ### Basic usage
32
+ ## Quickstart
57
33
 
58
34
  ```typescript
59
35
  import { TenxGraphClient, Message } from '10xgraph-client';
60
36
 
61
37
  const client = new TenxGraphClient({
62
38
  baseUrl: 'http://localhost:8000',
63
- authToken: 'your-token', // optional bearer auth
64
- debug: true, // optional
39
+ authToken: token, // a bearer token for the signed-in user
65
40
  });
66
41
 
67
- const result = await client.invoke([Message.text_message('Hello, how can you help me?', 'user')]);
68
-
42
+ // Request and response. Remote tools run automatically during invoke.
43
+ const result = await client.invoke(
44
+ [Message.text_message('Where is my order 1042?', 'user')],
45
+ { config: { thread_id: 'support-1042' } }
46
+ );
69
47
  console.log(result.messages);
48
+
49
+ // Server-sent events
50
+ for await (const chunk of client.stream([Message.text_message('And the refund status?', 'user')], {
51
+ config: { thread_id: 'support-1042' },
52
+ })) {
53
+ if (chunk.event === 'message') console.log(chunk.message?.content);
54
+ }
70
55
  ```
71
56
 
72
- Start a local server with `10xgraph api` (from the `10xgraph-api` package).
57
+ `stream()` returns an async generator of `StreamChunk`. `wsStream()` takes the same arguments and
58
+ streams over a WebSocket. Both accept `initial_state`, `config`, `recursion_limit`, `on_busy`
59
+ (`'wait' | 'cancel'`), `resume` with `interrupt_id`, `response_granularity` and `signal` (an
60
+ `AbortSignal` that cancels the request). A 409 throws `ConflictError` and is not retried.
73
61
 
74
- ### Authentication options
62
+ To answer a human-in-the-loop interrupt, read it from a chunk and resume the thread:
75
63
 
76
64
  ```typescript
77
- import { TenxGraphClient, basicAuth, headerAuth } from '10xgraph-client';
65
+ import { getInterrupt, approveInterrupt, rejectInterrupt } from '10xgraph-client';
78
66
 
79
- const bearerClient = new TenxGraphClient({
80
- baseUrl: 'https://api.example.com',
81
- authToken: process.env.TENXGRAPH_TOKEN,
82
- });
67
+ const interrupt = getInterrupt(chunk); // null when the chunk carries none
68
+ if (interrupt) {
69
+ await client.invoke([], { config: { thread_id }, ...approveInterrupt(interrupt) });
70
+ // or ...rejectInterrupt(interrupt)
71
+ }
72
+ ```
83
73
 
84
- const basicClient = new TenxGraphClient({
85
- baseUrl: 'https://api.example.com',
86
- auth: basicAuth('service-user', 'service-password'),
87
- });
74
+ ## What the client covers
88
75
 
89
- const apiKeyClient = new TenxGraphClient({
90
- baseUrl: 'https://api.example.com',
91
- auth: headerAuth('X-API-Key', process.env.TENXGRAPH_API_KEY!),
92
- });
76
+ | Area | Methods |
77
+ | --- | --- |
78
+ | Runs | `invoke`, `stream`, `wsStream`, `stopGraph` |
79
+ | Identity and server | `ping`, `me`, `graph`, `graphTools`, `graphStateSchema`, `observability` |
80
+ | Threads and messages | `threads`, `threadDetails`, `threadMessages`, `singleMessage`, `deleteMessage`, `updateThreadMessageFeedback`, `deleteThread` |
81
+ | Thread state | `threadState`, `updateThreadState`, `clearThreadState` |
82
+ | Memory store | `storeMemory`, `searchMemory`, `getMemory`, `updateMemory`, `deleteMemory`, `listMemories`, `forgetMemories` |
83
+ | Files | `uploadFile`, `getFile`, `listFiles`, `getFileInfo`, `getFileAccessUrl`, `deleteFile`, `getMultimodalConfig` |
84
+ | Background tasks | `runTask`, `scheduleTask`, `getTask`, `rescheduleTask`, `cancelTask` |
85
+ | Remote tools | `registerTool`, `registerToolHandler` |
86
+ | Realtime audio | `realtime` |
93
87
 
94
- const sessionClient = new TenxGraphClient({
95
- baseUrl: 'https://api.example.com',
96
- credentials: 'include',
97
- });
98
- ```
88
+ Every method that does not return a stream accepts a per-call `options` argument with an
89
+ `AbortSignal`. The full list with types is in the
90
+ [`TenxGraphClient` reference](https://10xgraph.com/docs/reference/client/client).
99
91
 
100
- ### Streaming chat
92
+ ### Threads, memory and files
101
93
 
102
94
  ```typescript
103
- const stream = client.stream([Message.text_message('Tell me a story', 'user')]);
95
+ const page = await client.threads({ limit: 20 });
96
+ const messages = await client.threadMessages('support-1042', { limit: 50 });
104
97
 
105
- for await (const chunk of stream) {
106
- if (chunk.event === 'message') {
107
- console.log(chunk.message?.content);
108
- }
109
- }
98
+ const upload = await client.uploadFile(file);
99
+ const msg = Message.withFile('Summarize this document', upload.data.file_id, upload.data.mime_type);
100
+ const accessUrl = await client.getFileAccessUrl(upload.data.file_id);
110
101
  ```
111
102
 
112
- ## Realtime audio (`/v1/graph/live`)
103
+ ### Background tasks
113
104
 
114
- Transport-only: you stream PCM16 in and get PCM16 out. Mic capture and playback are yours to wire.
105
+ Tasks marked `http=True` on the server can be started and read from the client:
115
106
 
116
- ```ts
117
- import { TenxGraphClient } from '10xgraph-client';
107
+ ```typescript
108
+ const { data } = await client.runTask('web_add', { kwargs: { a: 1, b: 2 } });
109
+ const task = await client.getTask(data.task_id);
110
+ ```
118
111
 
119
- const client = new TenxGraphClient({ baseUrl: 'http://localhost:8000', authToken });
112
+ `scheduleTask` takes a `schedule` with exactly one of `cron`, `at` or `every`; the server answers
113
+ 501 when it has no Redis. See [Background tasks](https://10xgraph.com/docs/server/background-tasks).
120
114
 
121
- const session = client.realtime(
122
- { model: 'gemini-3.8-live', modalities: 'AUDIO' },
123
- { reconnect: { maxAttempts: 5 } }
124
- );
115
+ ## Authentication and secure frontends
125
116
 
126
- session.on('audio', (pcm16, sampleRate) => playback(pcm16, sampleRate)); // PCM16 @ 24 kHz
127
- session.on('output_transcript', (e) => console.log(e.text));
128
- session.on('tool_call', (e) => console.log('tool', e.name, e.args));
129
- session.on('error', (e) => console.error(e.message));
117
+ ```typescript
118
+ import { TenxGraphClient, basicAuth, headerAuth } from '10xgraph-client';
130
119
 
131
- await session.ready; // socket open + init sent
132
- session.sendAudio(micChunk); // PCM16 @ 16 kHz (Uint8Array | ArrayBuffer)
133
- // push-to-talk: session.activityStart() / session.activityEnd()
134
- session.close(); // graceful end; disables reconnect
120
+ new TenxGraphClient({ baseUrl, authToken: token }); // bearer token
121
+ new TenxGraphClient({ baseUrl, authToken: () => session.accessToken }); // called before each request
122
+ new TenxGraphClient({ baseUrl, auth: basicAuth('service-user', 'service-password') });
123
+ new TenxGraphClient({ baseUrl, auth: headerAuth('X-API-Key', apiKey) });
124
+ new TenxGraphClient({ baseUrl, credentials: 'include' }); // cookie sessions
135
125
  ```
136
126
 
137
- Auth uses the browser-safe `10xgraph-bearer` subprotocol automatically. In Node < 21 (no global
138
- `WebSocket`), pass an implementation:
127
+ `setAuthToken(token)` swaps the token on a live client and `clearAuth()` removes it.
128
+
129
+ - The server decides who the caller is and what they may read. The client only carries the
130
+ identity. Roles, tenant columns and ownership are enforced on the server.
131
+ - Anything in a browser bundle is readable by the person using it, including `NEXT_PUBLIC_*`
132
+ variables. Never put a shared API key, a signing secret or a service credential in frontend code.
133
+ Use a server-side proxy that holds the secret, or give each signed-in user a short-lived token.
134
+ - Browsers cannot set headers on a WebSocket. For `wsStream()` and `realtime()` the client sends
135
+ the token as the second entry of the `Sec-WebSocket-Protocol` list, after the `10xgraph-bearer`
136
+ sentinel (`WS_BEARER_SUBPROTOCOL`). The token never goes in the URL.
137
+ - In Node versions without a global `WebSocket` (before 21), pass an implementation:
139
138
 
140
- ```ts
139
+ ```typescript
141
140
  import WebSocket from 'ws';
142
141
  const client = new TenxGraphClient({ baseUrl, authToken, webSocketImpl: WebSocket });
143
142
  ```
144
143
 
145
- ### File uploads and access URLs
146
-
147
- ```typescript
148
- const upload = await client.uploadFile(file);
149
-
150
- // Best URL for rendering/downloading in the UI.
151
- // Cloud-backed deployments typically return a signed URL here.
152
- const accessUrl = upload.data.direct_url ?? upload.data.url;
144
+ More in [Secure your frontend](https://10xgraph.com/docs/client/secure-your-frontend) and the
145
+ [security model](https://10xgraph.com/docs/production/security-model).
153
146
 
154
- const fileInfo = await client.getFileInfo(upload.data.file_id);
155
- const fileUrl = await client.getFileAccessUrl(upload.data.file_id);
147
+ ## Remote tools
156
148
 
157
- const msg = Message.withFile('Summarize this document', upload.data.file_id, upload.data.mime_type);
158
- ```
159
-
160
- ### Tool registration
161
-
162
- **Important:** remote tools (registered client-side) should **only** be used for browser-level APIs
163
- like `localStorage` or `navigator.geolocation`. For most operations (database queries, external API
164
- calls, calculations), define your tools in the Python backend instead. See
165
- [Remote tools](https://10xgraph.com/docs/client/remote-tools) for details.
149
+ Remote tools run in the user's browser, for browser-only APIs such as `localStorage` or
150
+ `navigator.geolocation`. Database queries, external API calls and calculations belong in tools on
151
+ the server.
166
152
 
167
153
  ```typescript
168
- // Matching trusted schema must be declared in the server's 10xgraph.json.
169
- client.registerToolHandler('get_weather', async ({ location }) => {
170
- return { temperature: 72, conditions: 'sunny' };
154
+ // The matching schema must be declared in the server's 10xgraph.json.
155
+ client.registerToolHandler('get_location', async () => {
156
+ const pos = await new Promise<GeolocationPosition>((resolve, reject) =>
157
+ navigator.geolocation.getCurrentPosition(resolve, reject)
158
+ );
159
+ return { lat: pos.coords.latitude, lon: pos.coords.longitude };
171
160
  });
172
161
 
173
- // Tools execute automatically during invoke
174
- const result = await client.invoke([Message.text_message('What is the weather in NYC?', 'user')]);
162
+ // The server asks for the tool during the run; the client runs it and sends the result back.
163
+ const result = await client.invoke([Message.text_message('Find a store near me', 'user')]);
175
164
  ```
176
165
 
177
- Declare model-facing metadata in the server's `10xgraph.json`, never from an untrusted client:
166
+ Model-facing metadata is declared on the server, never by an untrusted client:
178
167
 
179
168
  ```json
180
169
  {
181
170
  "remote_tools": [
182
171
  {
183
172
  "node": "assistant",
184
- "name": "get_weather",
185
- "description": "Get current weather for a location",
186
- "parameters": {
187
- "type": "object",
188
- "properties": { "location": { "type": "string" } },
189
- "required": ["location"]
190
- }
173
+ "name": "get_location",
174
+ "description": "Get the user's current coordinates",
175
+ "parameters": { "type": "object", "properties": {} }
191
176
  }
192
177
  ]
193
178
  }
194
179
  ```
195
180
 
196
- No client setup call is required or available.
197
-
198
- ## Documentation
199
-
200
- Full documentation lives at **[10xgraph.com/docs](https://10xgraph.com/docs/client)**.
201
-
202
- ### Guides
203
-
204
- - **[Create a client](https://10xgraph.com/docs/client/create-client)**: setup and first request
205
- - **[Invoke an agent](https://10xgraph.com/docs/client/invoke-agent)**: request/response with tool execution
206
- - **[Stream responses](https://10xgraph.com/docs/client/stream-responses)**: real-time streaming
207
- - **[Remote tools](https://10xgraph.com/docs/client/remote-tools)**: when to use client-side tools
208
- - **[Realtime audio](https://10xgraph.com/docs/client/realtime-audio)**: the `/v1/graph/live` session
209
- - **[Error handling](https://10xgraph.com/docs/client/error-handling)**: error classes and recovery
210
-
211
- ### Reference
212
-
213
- - **[`TenxGraphClient`](https://10xgraph.com/docs/reference/client/client)**: constructor config and every method
214
- - **[`Message` and content blocks](https://10xgraph.com/docs/reference/client/message)**
215
- - **[Auth](https://10xgraph.com/docs/reference/client/auth)** and **[Errors](https://10xgraph.com/docs/reference/client/errors)**
216
- - **[Troubleshooting](https://10xgraph.com/docs/troubleshooting/client)**: common issues and solutions
217
-
218
- ## Key APIs
181
+ No client setup call is required or available. See
182
+ [Remote tools](https://10xgraph.com/docs/client/remote-tools).
219
183
 
220
- ### `invoke()`: batch processing
184
+ ## Realtime audio
221
185
 
222
- Execute the agent with an automatic tool execution loop:
186
+ Transport only: you stream PCM16 in and get PCM16 out, and wire microphone capture and playback
187
+ yourself.
223
188
 
224
189
  ```typescript
225
- const result = await client.invoke(messages, {
226
- recursion_limit: 25,
227
- response_granularity: 'full',
228
- });
229
- ```
230
-
231
- Optional: `on_busy: 'wait' | 'cancel'` controls what happens when the thread already has an active
232
- run, and `resume` with `interrupt_id` answers an open interrupt. A 409 throws `ConflictError`
233
- (not retried automatically).
234
-
235
- ### `stream()`: real-time streaming
236
-
237
- ```typescript
238
- const stream = client.stream(messages);
239
- for await (const chunk of stream) {
240
- // Process chunks in real-time
241
- }
242
- ```
243
-
244
- ### `graphStateSchema()`: dynamic schema
190
+ const session = client.realtime(
191
+ { model: 'gemini-3.8-live', modalities: 'AUDIO' },
192
+ { reconnect: { maxAttempts: 5 } }
193
+ );
245
194
 
246
- Get the agent state schema for form generation and validation:
195
+ session.on('audio', (pcm16, sampleRate) => playback(pcm16, sampleRate)); // PCM16 @ 24 kHz
196
+ session.on('output_transcript', (e) => console.log(e.text));
197
+ session.on('tool_call', (e) => console.log('tool', e.name, e.args));
198
+ session.on('error', (e) => console.error(e.message));
247
199
 
248
- ```typescript
249
- const schema = await client.graphStateSchema();
200
+ await session.ready; // socket open and init sent
201
+ session.sendAudio(micChunk); // PCM16 @ 16 kHz (Uint8Array | ArrayBuffer)
202
+ // push-to-talk: session.activityStart() / session.activityEnd()
203
+ session.close(); // graceful end; disables reconnect
250
204
  ```
251
205
 
252
- ### `graphTools()`: tool inventory
253
-
254
- List the tools the graph's tool nodes expose, grouped by node. Each tool is tagged with its
255
- source (`local`, `mcp`, or `remote`):
256
-
257
- ```typescript
258
- const { data } = await client.graphTools();
259
- // data.nodes[].tools[] -> { name, description, source, parameters }
260
- ```
206
+ The server honours `model` only when it lists it in `websocket.realtime_models`. See
207
+ [Realtime audio](https://10xgraph.com/docs/client/realtime-audio).
261
208
 
262
- ### `observability(threadId, runId?)`: run traces
209
+ ## Errors
263
210
 
264
- Fetch the reconstructed trace for a run (spans, events, and cost). Defaults to the thread's
265
- latest run:
211
+ Every failure is a `TenxGraphError` or a subclass, so `instanceof` works:
266
212
 
267
213
  ```typescript
268
- const trace = await client.observability(threadId);
269
- const specific = await client.observability(threadId, runId);
214
+ import { TenxGraphError, AuthenticationError, RateLimitError, ConflictError } from '10xgraph-client';
215
+
216
+ try {
217
+ await client.invoke(messages);
218
+ } catch (err) {
219
+ if (err instanceof RateLimitError) {
220
+ await sleep((err.retryAfterSeconds ?? 1) * 1000); // set when the server sends a hint
221
+ } else if (err instanceof AuthenticationError) {
222
+ // refresh the token
223
+ } else if (err instanceof TenxGraphError) {
224
+ console.error(err.statusCode, err.errorCode, err.requestId, err.message);
225
+ } else {
226
+ throw err;
227
+ }
228
+ }
270
229
  ```
271
230
 
272
- ## Examples
273
-
274
- The [`examples/`](examples/) directory has complete working examples:
275
-
276
- - **[invoke-example.ts](examples/invoke-example.ts)**: basic invoke with tool execution
277
- - **[stream-example.ts](examples/stream-example.ts)**: streaming responses
278
- - **[state-schema-examples.ts](examples/state-schema-examples.ts)**: form generation and validation
279
-
280
- ## Architecture
281
-
282
- ```
283
- ┌──────────────────────┐
284
- │ Your application │
285
- └──────────┬───────────┘
286
- │ TenxGraphClient
287
- ▼
288
- ┌──────────────────────┐
289
- │ 10xgraph-client │ <- this library
290
- │ client, tools, │
291
- │ messages │
292
- └──────────┬───────────┘
293
- │ HTTP/HTTPS + WebSocket
294
- ▼
295
- ┌──────────────────────┐
296
- │ 10xgraph-api │ <- your backend
297
- │ (10xgraph api) │
298
- └──────────────────────┘
299
- ```
231
+ Other subclasses include `PermissionError`, `NotFoundError`, `ValidationError`, `ServerError`,
232
+ `RequestTimeoutError`, `NetworkError`, `WebSocketError` and `StreamError`. See
233
+ [Error handling](https://10xgraph.com/docs/client/error-handling).
300
234
 
301
235
  ## Configuration
302
236
 
303
237
  ```typescript
304
238
  const client = new TenxGraphClient({
305
239
  baseUrl: string, // Required: API base URL
306
- authToken?: string, // Optional: bearer token
240
+ authToken?: string | (() => string | null | undefined), // Optional: bearer token or getter
307
241
  auth?: TenxGraphAuth, // Optional: bearer/basic/custom header auth
308
242
  headers?: HeadersInit, // Optional: extra headers for every request
309
243
  credentials?: RequestCredentials, // Optional: cookie/session auth
@@ -313,6 +247,18 @@ const client = new TenxGraphClient({
313
247
  });
314
248
  ```
315
249
 
250
+ ## One stack, backend to frontend
251
+
252
+ | Layer | Package | What it is |
253
+ | --- | --- | --- |
254
+ | Core | [`10xgraph`](https://github.com/10xGraph/10xGraph) (PyPI, import `tenxgraph`) | Graphs, agents, tools, state, storage |
255
+ | Server | [`10xgraph-api`](https://github.com/10xGraph/10xgraph-api) (PyPI, command `10xgraph`) | API server, auth, jobs, deploy files |
256
+ | Client | `10xgraph-client` (this package) | Typed TypeScript client |
257
+ | Docs | [10xgraph.com/docs/client](https://10xgraph.com/docs/client) | Guides and reference |
258
+
259
+ Start a local server with `10xgraph dev`. For a Next.js or React app see
260
+ [Next.js and React](https://10xgraph.com/docs/client/nextjs-and-react).
261
+
316
262
  ## Migrating from `@10xscale/agentflow-client`
317
263
 
318
264
  The project was renamed from Agentflow to **10xGraph** because "Agentflow" is shared by several
@@ -331,7 +277,7 @@ Steps:
331
277
 
332
278
  1. `npm uninstall @10xscale/agentflow-client && npm install 10xgraph-client`
333
279
  2. Replace `'@10xscale/agentflow-client'` with `'10xgraph-client'` in your imports.
334
- 3. Upgrade the server to `10xgraph-api` >= 0.7.0 if you use `wsStream()` or `realtime()`.
280
+ 3. Upgrade the server to `10xgraph-api` 1.0 if you use `wsStream()` or `realtime()`.
335
281
  4. Optionally rename `AgentFlow*` identifiers to `TenxGraph*`. The old names are exported as
336
282
  deprecated aliases of the same classes and types, so `instanceof AgentFlowError` keeps working.
337
283
  They are removed in 2.0.
@@ -344,28 +290,26 @@ One observable difference: errors now report `error.name === 'TenxGraphError'` i
344
290
  Ships dual ESM + CJS with types. `import` resolves `dist/index.js` (ESM); `require` resolves
345
291
  `dist/index.cjs`. Tree-shakeable (`"sideEffects": false`).
346
292
 
347
- ## Testing
348
-
349
- ```bash
350
- npm test # watch mode
351
- npm run test:run # run once
352
- npm run build # build the library
353
- ```
354
-
355
293
  ## TypeScript support
356
294
 
357
295
  ```typescript
358
296
  import type {
359
- TenxGraphClient,
360
- Message,
297
+ TenxGraphConfig,
361
298
  ToolRegistration,
362
299
  InvokeResult,
363
300
  StreamChunk,
364
301
  AgentState,
365
- AgentStateSchema,
366
302
  } from '10xgraph-client';
367
303
  ```
368
304
 
305
+ ## Testing
306
+
307
+ ```bash
308
+ npm test # watch mode
309
+ npm run test:run # run once
310
+ npm run build # build the library
311
+ ```
312
+
369
313
  ## Contributing
370
314
 
371
315
  **Be the first community contributor on this wall.**