@aexhq/sdk 0.40.6 → 0.40.8
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/README.md +159 -159
- package/dist/_contracts/asset-upload-helper.d.ts +38 -0
- package/dist/_contracts/asset-upload-helper.js +111 -0
- package/dist/_contracts/internal.d.ts +5 -9
- package/dist/_contracts/internal.js +5 -79
- package/dist/_contracts/operations.d.ts +9 -2
- package/dist/_contracts/operations.js +141 -16
- package/dist/_contracts/retry-core.d.ts +27 -0
- package/dist/_contracts/retry-core.js +75 -0
- package/dist/_contracts/runtime-types.d.ts +6 -0
- package/dist/_contracts/stable.d.ts +10 -5
- package/dist/_contracts/stable.js +10 -5
- package/dist/asset-upload.d.ts +2 -1
- package/dist/asset-upload.js +28 -61
- package/dist/asset-upload.js.map +1 -1
- package/dist/cli.mjs +297 -80
- package/dist/cli.mjs.sha256 +1 -1
- package/dist/client.d.ts +5 -0
- package/dist/client.js +8 -13
- package/dist/client.js.map +1 -1
- package/dist/retry.js +13 -41
- package/dist/retry.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/authentication.md +125 -125
- package/docs/billing.md +118 -118
- package/docs/concepts/agent-tools.md +66 -66
- package/docs/concepts/composition.md +37 -37
- package/docs/concepts/providers-and-runtimes.md +54 -54
- package/docs/concepts/runs.md +49 -49
- package/docs/concepts/subagents.md +88 -88
- package/docs/credentials.md +125 -125
- package/docs/defaults.md +64 -64
- package/docs/errors.md +196 -196
- package/docs/events.md +243 -243
- package/docs/limits-and-quotas.md +144 -144
- package/docs/limits.md +50 -50
- package/docs/mcp.md +44 -44
- package/docs/networking.md +163 -163
- package/docs/outputs.md +267 -267
- package/docs/public-surface.json +77 -77
- package/docs/quickstart.md +119 -119
- package/docs/release.md +38 -38
- package/docs/retries.md +129 -129
- package/docs/run-config.md +58 -58
- package/docs/run-record.md +55 -55
- package/docs/secrets.md +125 -125
- package/docs/testing.md +35 -35
- package/docs/vision-skills.md +91 -91
- package/docs/webhooks.md +127 -127
- package/examples/feature-tour.ts +282 -282
- package/examples/spike-settle-latency.ts +125 -125
- package/package.json +1 -1
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Composition
|
|
3
|
-
description: The primitives used to assemble each run.
|
|
4
|
-
icon: Blocks
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
aex composes an agent from explicit per-session inputs. The SDK materializes local
|
|
8
|
-
bytes before the session lands and the platform mounts them into the managed
|
|
9
|
-
runtime before the first agent turn.
|
|
10
|
-
|
|
11
|
-
| Need | Primitive |
|
|
12
|
-
| --- | --- |
|
|
1
|
+
---
|
|
2
|
+
title: Composition
|
|
3
|
+
description: The primitives used to assemble each run.
|
|
4
|
+
icon: Blocks
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
aex composes an agent from explicit per-session inputs. The SDK materializes local
|
|
8
|
+
bytes before the session lands and the platform mounts them into the managed
|
|
9
|
+
runtime before the first agent turn.
|
|
10
|
+
|
|
11
|
+
| Need | Primitive |
|
|
12
|
+
| --- | --- |
|
|
13
13
|
| Instructional skill bundles | `Skill.fromDir`, `Skill.fromUrl`, `Skill.fromFiles` |
|
|
14
|
-
| Agent instructions | `AgentsMd.fromPath`, `AgentsMd.fromContent` |
|
|
15
|
-
| Reference files and folders | `File.fromPath`, `File.fromBytes` |
|
|
16
|
-
| Remote tools | `McpServer.remote`, `McpServer.fromId` |
|
|
17
|
-
| Non-secret runtime settings | `environment.variables`, `environment.packages`, `environment.networking` |
|
|
18
|
-
| Runtime secrets for your code | `Secret.value`, `Secret.ref`, `environment.secrets` |
|
|
19
|
-
|
|
20
|
-
```ts
|
|
14
|
+
| Agent instructions | `AgentsMd.fromPath`, `AgentsMd.fromContent` |
|
|
15
|
+
| Reference files and folders | `File.fromPath`, `File.fromBytes` |
|
|
16
|
+
| Remote tools | `McpServer.remote`, `McpServer.fromId` |
|
|
17
|
+
| Non-secret runtime settings | `environment.variables`, `environment.packages`, `environment.networking` |
|
|
18
|
+
| Runtime secrets for your code | `Secret.value`, `Secret.ref`, `environment.secrets` |
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
21
|
import { AgentsMd, File, McpServer, Models, Secret, Skill } from "@aexhq/sdk";
|
|
22
|
-
|
|
23
|
-
await aex.run({
|
|
24
|
-
model: Models.CLAUDE_HAIKU_4_5,
|
|
25
|
-
message: "Use the attached docs and tools to produce a report.",
|
|
26
|
-
agentsMd: [await AgentsMd.fromContent("Follow the repo conventions.", { name: "repo-rules" })],
|
|
27
|
-
files: [await File.fromPath("./input")],
|
|
22
|
+
|
|
23
|
+
await aex.run({
|
|
24
|
+
model: Models.CLAUDE_HAIKU_4_5,
|
|
25
|
+
message: "Use the attached docs and tools to produce a report.",
|
|
26
|
+
agentsMd: [await AgentsMd.fromContent("Follow the repo conventions.", { name: "repo-rules" })],
|
|
27
|
+
files: [await File.fromPath("./input")],
|
|
28
28
|
skills: [await Skill.fromDir("./skills/report-writer", { name: "report-writer" })],
|
|
29
|
-
mcpServers: [McpServer.remote({ name: "github", url: "https://example.com/mcp" })],
|
|
30
|
-
environment: {
|
|
31
|
-
secrets: { INTERNAL_API_TOKEN: Secret.value(process.env.INTERNAL_API_TOKEN!) },
|
|
32
|
-
networking: { mode: "limited", allowedHosts: ["api.example.com"] }
|
|
33
|
-
},
|
|
34
|
-
apiKeys: { anthropic: process.env.ANTHROPIC_API_KEY! }
|
|
35
|
-
});
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
Secrets stay out of reusable configs. Provider keys go in the top-level `apiKeys`
|
|
39
|
-
map; reusable or per-run values for your own code go in `environment.secrets`.
|
|
40
|
-
Your code then makes normal HTTP calls with the standard client for that service.
|
|
29
|
+
mcpServers: [McpServer.remote({ name: "github", url: "https://example.com/mcp" })],
|
|
30
|
+
environment: {
|
|
31
|
+
secrets: { INTERNAL_API_TOKEN: Secret.value(process.env.INTERNAL_API_TOKEN!) },
|
|
32
|
+
networking: { mode: "limited", allowedHosts: ["api.example.com"] }
|
|
33
|
+
},
|
|
34
|
+
apiKeys: { anthropic: process.env.ANTHROPIC_API_KEY! }
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Secrets stay out of reusable configs. Provider keys go in the top-level `apiKeys`
|
|
39
|
+
map; reusable or per-run values for your own code go in `environment.secrets`.
|
|
40
|
+
Your code then makes normal HTTP calls with the standard client for that service.
|
|
@@ -1,54 +1,54 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Providers & runtimes
|
|
3
|
-
description: How provider selection maps to managed runtime execution.
|
|
4
|
-
icon: Network
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
aex exposes one submission shape across supported providers:
|
|
8
|
-
|
|
9
|
-
| Provider | Selector |
|
|
10
|
-
| --- | --- |
|
|
11
|
-
| Anthropic | `Providers.ANTHROPIC` |
|
|
12
|
-
| DeepSeek | `Providers.DEEPSEEK` |
|
|
13
|
-
| OpenAI | `Providers.OPENAI` |
|
|
14
|
-
| Gemini | `Providers.GEMINI` |
|
|
15
|
-
| Mistral | `Providers.MISTRAL` |
|
|
16
|
-
| OpenRouter | `Providers.OPENROUTER` |
|
|
17
|
-
| Doubao | `Providers.DOUBAO` |
|
|
18
|
-
| Doubao China | `Providers.DOUBAO_CN` |
|
|
19
|
-
|
|
20
|
-
All submissions run on the managed runtime. The optional `runtime` option picks
|
|
21
|
-
a managed machine-size preset — use `Sizes.*` in TypeScript (e.g.
|
|
22
|
-
`runtime: Sizes.SHARED_0_25X_1GB`) or `--runtime-size` in the CLI. Omit it for
|
|
23
|
-
the default size; there is no alternative runtime backend to select.
|
|
24
|
-
|
|
25
|
-
## Selection
|
|
26
|
-
|
|
27
|
-
### TypeScript
|
|
28
|
-
|
|
29
|
-
```ts
|
|
30
|
-
import { Models, Providers } from "@aexhq/sdk";
|
|
31
|
-
|
|
32
|
-
await aex.run({
|
|
33
|
-
provider: Providers.OPENAI,
|
|
34
|
-
model: Models.GPT_4_1,
|
|
35
|
-
message: "Summarise the attached files.",
|
|
36
|
-
apiKeys: { openai: process.env.OPENAI_API_KEY! }
|
|
37
|
-
});
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
### CLI
|
|
41
|
-
|
|
42
|
-
```bash
|
|
43
|
-
aex run \
|
|
44
|
-
--api-key "$AEX_API_KEY" \
|
|
45
|
-
--provider openai \
|
|
46
|
-
--openai-api-key "$OPENAI_API_KEY" \
|
|
47
|
-
--model gpt-4.1 \
|
|
48
|
-
--prompt "Summarise the attached files." \
|
|
49
|
-
--follow
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
Events, outputs, cleanup, and downloads use the same SDK and CLI surface for
|
|
53
|
-
every provider. For the exact supported model list, use the generated
|
|
54
|
-
[provider/runtime capability matrix](../provider-runtime-capabilities.md).
|
|
1
|
+
---
|
|
2
|
+
title: Providers & runtimes
|
|
3
|
+
description: How provider selection maps to managed runtime execution.
|
|
4
|
+
icon: Network
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
aex exposes one submission shape across supported providers:
|
|
8
|
+
|
|
9
|
+
| Provider | Selector |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| Anthropic | `Providers.ANTHROPIC` |
|
|
12
|
+
| DeepSeek | `Providers.DEEPSEEK` |
|
|
13
|
+
| OpenAI | `Providers.OPENAI` |
|
|
14
|
+
| Gemini | `Providers.GEMINI` |
|
|
15
|
+
| Mistral | `Providers.MISTRAL` |
|
|
16
|
+
| OpenRouter | `Providers.OPENROUTER` |
|
|
17
|
+
| Doubao | `Providers.DOUBAO` |
|
|
18
|
+
| Doubao China | `Providers.DOUBAO_CN` |
|
|
19
|
+
|
|
20
|
+
All submissions run on the managed runtime. The optional `runtime` option picks
|
|
21
|
+
a managed machine-size preset — use `Sizes.*` in TypeScript (e.g.
|
|
22
|
+
`runtime: Sizes.SHARED_0_25X_1GB`) or `--runtime-size` in the CLI. Omit it for
|
|
23
|
+
the default size; there is no alternative runtime backend to select.
|
|
24
|
+
|
|
25
|
+
## Selection
|
|
26
|
+
|
|
27
|
+
### TypeScript
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import { Models, Providers } from "@aexhq/sdk";
|
|
31
|
+
|
|
32
|
+
await aex.run({
|
|
33
|
+
provider: Providers.OPENAI,
|
|
34
|
+
model: Models.GPT_4_1,
|
|
35
|
+
message: "Summarise the attached files.",
|
|
36
|
+
apiKeys: { openai: process.env.OPENAI_API_KEY! }
|
|
37
|
+
});
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### CLI
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
aex run \
|
|
44
|
+
--api-key "$AEX_API_KEY" \
|
|
45
|
+
--provider openai \
|
|
46
|
+
--openai-api-key "$OPENAI_API_KEY" \
|
|
47
|
+
--model gpt-4.1 \
|
|
48
|
+
--prompt "Summarise the attached files." \
|
|
49
|
+
--follow
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Events, outputs, cleanup, and downloads use the same SDK and CLI surface for
|
|
53
|
+
every provider. For the exact supported model list, use the generated
|
|
54
|
+
[provider/runtime capability matrix](../provider-runtime-capabilities.md).
|
package/docs/concepts/runs.md
CHANGED
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Runs
|
|
3
|
-
description: The durable unit aex submits, observes, and archives.
|
|
4
|
-
icon: Play
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
A run is a durable, resumable **session**: the model, system message, composition
|
|
8
|
-
primitives, output policy, and per-provider keys you open it with, plus every
|
|
9
|
-
turn you send to it. aex snapshots the non-secret inputs, holds secrets for the
|
|
10
|
-
session lifecycle, dispatches each turn through the managed runtime, and records
|
|
11
|
-
status, typed events, and outputs. Sessions are the low-level API; `run()` is the
|
|
12
|
-
one-shot convenience wrapper over them.
|
|
13
|
-
|
|
14
|
-
```ts
|
|
15
|
-
import { Aex, Models } from "@aexhq/sdk";
|
|
16
|
-
|
|
17
|
-
const aex = new Aex({ apiKey: process.env.AEX_API_KEY! });
|
|
18
|
-
|
|
19
|
-
const session = await aex.openSession({
|
|
20
|
-
provider: "anthropic",
|
|
21
|
-
model: Models.CLAUDE_HAIKU_4_5,
|
|
22
|
-
apiKeys: { anthropic: process.env.ANTHROPIC_API_KEY! }
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
const turn = session.send("Write the report and save it as a file.");
|
|
26
|
-
for await (const event of turn) {
|
|
27
|
-
console.log(event.type);
|
|
28
|
-
}
|
|
29
|
-
await turn.done();
|
|
30
|
-
|
|
31
|
-
await session.wait();
|
|
32
|
-
await session.download({ to: "./session.zip" });
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
The same durable record backs SDK and CLI reads. From the handle use `refresh`,
|
|
36
|
-
`unit`, `wait`, and `download` for lifecycle, plus the grouped read accessors —
|
|
37
|
-
`messages()`, `events()`, and `outputs()` (each with `list()`/`last()`/`first()`,
|
|
38
|
-
and `events().stream()` / `events().streamEnvelopes()` / `outputs().read(...)` for
|
|
39
|
-
streaming and byte-capped reads) — to inspect the session live or after it parks;
|
|
40
|
-
from the client, `aex.sessions.list()` / `aex.sessions.get(id)` read across the
|
|
41
|
-
workspace (CLI mirrors: `aex sessions` and `aex runs` list the workspace's
|
|
42
|
-
sessions/runs newest-first).
|
|
43
|
-
|
|
44
|
-
Use `idempotencyKey` when retrying `openSession` or `send` from your own
|
|
45
|
-
workflow. aex hashes the normalized non-secret submission, so a retry with the
|
|
46
|
-
same key and same body returns the existing session while a mismatched body fails
|
|
47
|
-
with an idempotency conflict.
|
|
48
|
-
|
|
49
|
-
aex selects product placement server-side. There is no region selector.
|
|
1
|
+
---
|
|
2
|
+
title: Runs
|
|
3
|
+
description: The durable unit aex submits, observes, and archives.
|
|
4
|
+
icon: Play
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
A run is a durable, resumable **session**: the model, system message, composition
|
|
8
|
+
primitives, output policy, and per-provider keys you open it with, plus every
|
|
9
|
+
turn you send to it. aex snapshots the non-secret inputs, holds secrets for the
|
|
10
|
+
session lifecycle, dispatches each turn through the managed runtime, and records
|
|
11
|
+
status, typed events, and outputs. Sessions are the low-level API; `run()` is the
|
|
12
|
+
one-shot convenience wrapper over them.
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import { Aex, Models } from "@aexhq/sdk";
|
|
16
|
+
|
|
17
|
+
const aex = new Aex({ apiKey: process.env.AEX_API_KEY! });
|
|
18
|
+
|
|
19
|
+
const session = await aex.openSession({
|
|
20
|
+
provider: "anthropic",
|
|
21
|
+
model: Models.CLAUDE_HAIKU_4_5,
|
|
22
|
+
apiKeys: { anthropic: process.env.ANTHROPIC_API_KEY! }
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const turn = session.send("Write the report and save it as a file.");
|
|
26
|
+
for await (const event of turn) {
|
|
27
|
+
console.log(event.type);
|
|
28
|
+
}
|
|
29
|
+
await turn.done();
|
|
30
|
+
|
|
31
|
+
await session.wait();
|
|
32
|
+
await session.download({ to: "./session.zip" });
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The same durable record backs SDK and CLI reads. From the handle use `refresh`,
|
|
36
|
+
`unit`, `wait`, and `download` for lifecycle, plus the grouped read accessors —
|
|
37
|
+
`messages()`, `events()`, and `outputs()` (each with `list()`/`last()`/`first()`,
|
|
38
|
+
and `events().stream()` / `events().streamEnvelopes()` / `outputs().read(...)` for
|
|
39
|
+
streaming and byte-capped reads) — to inspect the session live or after it parks;
|
|
40
|
+
from the client, `aex.sessions.list()` / `aex.sessions.get(id)` read across the
|
|
41
|
+
workspace (CLI mirrors: `aex sessions` and `aex runs` list the workspace's
|
|
42
|
+
sessions/runs newest-first).
|
|
43
|
+
|
|
44
|
+
Use `idempotencyKey` when retrying `openSession` or `send` from your own
|
|
45
|
+
workflow. aex hashes the normalized non-secret submission, so a retry with the
|
|
46
|
+
same key and same body returns the existing session while a mismatched body fails
|
|
47
|
+
with an idempotency conflict.
|
|
48
|
+
|
|
49
|
+
aex selects product placement server-side. There is no region selector.
|
|
@@ -1,88 +1,88 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Subagents
|
|
3
|
-
description: Delegate bounded sub-tasks to child agent runs with the subagent tool.
|
|
4
|
-
icon: GitFork
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
A run can delegate bounded sub-tasks to **child agent runs** with the built-in
|
|
8
|
-
`subagent` tool. Delegation is agent-driven: the model decides to fan work out,
|
|
9
|
-
each child is a real run with its own record, and the parent collects results
|
|
10
|
-
as the children finish. There is no client-side parent/child API — lineage is
|
|
11
|
-
session-internal.
|
|
12
|
-
|
|
13
|
-
## How the tool works
|
|
14
|
-
|
|
15
|
-
The agent calls `subagent` with a `prompt` and a `model` (both required), plus
|
|
16
|
-
optional `system`, `provider`, `runtimeSize`, `timeout`,
|
|
17
|
-
`includeBuiltinTools`, `tools` (builtin-tool names for the child), `skills`,
|
|
18
|
-
and `files`. The call is **always async**: on a successful spawn it returns
|
|
19
|
-
immediately with the child run id, and the parent keeps working while the child
|
|
20
|
-
runs. When a child settles, the parent is notified in its loop, and it reads
|
|
21
|
-
the child's status and captured outputs on demand with the companion
|
|
22
|
-
`subagent_result` tool.
|
|
23
|
-
|
|
24
|
-
Children inherit the parent's vaulted BYOK provider keys server-side — the
|
|
25
|
-
child submission carries no secrets. Include a provider key for every provider
|
|
26
|
-
your subagents may use when you open the parent session (a parent holding no
|
|
27
|
-
key for the child's provider gets a clear `parent_missing_provider_key` tool
|
|
28
|
-
error). See [Credentials](../credentials.md).
|
|
29
|
-
|
|
30
|
-
## Depth and breadth limits
|
|
31
|
-
|
|
32
|
-
Delegation is bounded by two server-enforced lineage limits:
|
|
33
|
-
|
|
34
|
-
| Limit | Value | Behavior at the limit |
|
|
35
|
-
| --- | --- | --- |
|
|
36
|
-
| Max depth | **5** — the root run is depth 0 and may spawn down to depth 5; a depth-5 run may not spawn further | The spawn is rejected with a `depth_exceeded` tool error (the parent keeps running). |
|
|
37
|
-
| Concurrent children per lineage root | **1000** live (non-terminal) descendants by default; hard platform ceiling **4096** | Further spawns are refused until a child settles. |
|
|
38
|
-
|
|
39
|
-
The whole descendant subtree of one root shares a single depth and breadth
|
|
40
|
-
budget, enforced server-side at every level — a grandchild spawn counts against
|
|
41
|
-
the same root budget as a direct child. Values are mirrored in
|
|
42
|
-
[Limits & quotas](../limits-and-quotas.md).
|
|
43
|
-
|
|
44
|
-
## Where children run: `in-process` vs `container`
|
|
45
|
-
|
|
46
|
-
By default a child runs **in-process**: it executes as a sibling agent process
|
|
47
|
-
inside the parent's own machine, sharing the parent's CPU, memory, and
|
|
48
|
-
lifetime. This is the platform default shipped today.
|
|
49
|
-
|
|
50
|
-
- **No extra runtime cost.** The parent's machine is the billable unit, so
|
|
51
|
-
in-process children bill **$0 of additional runtime** — fan-out is priced by
|
|
52
|
-
the parent box, however many children it hosts. (Model-token spend is still
|
|
53
|
-
whatever each child's provider calls cost on your BYOK key.)
|
|
54
|
-
- **Shared capacity.** N children share the parent's fixed CPU/memory. For
|
|
55
|
-
large fan-outs, size the parent up (`runtime`) rather than assuming each
|
|
56
|
-
child gets its own machine.
|
|
57
|
-
- **Joined lifecycle.** The parent's terminal waits for its in-process children,
|
|
58
|
-
and their results are folded into the parent's per-child accounting. Platform
|
|
59
|
-
recovery re-spawns in-process children exactly once if the parent's machine
|
|
60
|
-
is replaced mid-run — settled children are never re-run.
|
|
61
|
-
|
|
62
|
-
The escape valve is `host: "container"`: the child is dispatched to its **own
|
|
63
|
-
isolated machine** with its own runtime size and its own runtime billing, and
|
|
64
|
-
the parent does not host it. Use it when a child needs guaranteed capacity,
|
|
65
|
-
isolation from the parent's filesystem/CPU, or a different machine size than
|
|
66
|
-
the parent can share.
|
|
67
|
-
|
|
68
|
-
## Lineage and observability
|
|
69
|
-
|
|
70
|
-
Every child — in-process or container — is a first-class run record:
|
|
71
|
-
|
|
72
|
-
- The parent's transcript logs each spawn with the child's run id.
|
|
73
|
-
- Each child has its own status, typed event timeline, and captured outputs.
|
|
74
|
-
The child's events and outputs are readable by id
|
|
75
|
-
(`aex.sessions.outputs(id)` in the SDK, or the CLI's `aex events` /
|
|
76
|
-
`aex outputs`). Child runs are not served by the session read surface
|
|
77
|
-
today — `aex.sessions.get(id)` / `aex sessions` / the CLI's `aex status`
|
|
78
|
-
answer `not_found` for a child id.
|
|
79
|
-
- The child's outputs are handed back to the parent via `subagent_result`, and
|
|
80
|
-
they remain independently downloadable after the lineage finishes.
|
|
81
|
-
|
|
82
|
-
## Bounding delegation
|
|
83
|
-
|
|
84
|
-
- Turn delegation off for a run by cherry-picking builtins without `subagent`
|
|
85
|
-
(see [Agent tools](agent-tools.md)) or setting `includeBuiltinTools: false`.
|
|
86
|
-
- A per-session spend cap (`overrides.maxSpendUsd`) bounds the parent's spend.
|
|
87
|
-
- The depth/breadth limits above are platform defaults and are not settable
|
|
88
|
-
per-session today.
|
|
1
|
+
---
|
|
2
|
+
title: Subagents
|
|
3
|
+
description: Delegate bounded sub-tasks to child agent runs with the subagent tool.
|
|
4
|
+
icon: GitFork
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
A run can delegate bounded sub-tasks to **child agent runs** with the built-in
|
|
8
|
+
`subagent` tool. Delegation is agent-driven: the model decides to fan work out,
|
|
9
|
+
each child is a real run with its own record, and the parent collects results
|
|
10
|
+
as the children finish. There is no client-side parent/child API — lineage is
|
|
11
|
+
session-internal.
|
|
12
|
+
|
|
13
|
+
## How the tool works
|
|
14
|
+
|
|
15
|
+
The agent calls `subagent` with a `prompt` and a `model` (both required), plus
|
|
16
|
+
optional `system`, `provider`, `runtimeSize`, `timeout`,
|
|
17
|
+
`includeBuiltinTools`, `tools` (builtin-tool names for the child), `skills`,
|
|
18
|
+
and `files`. The call is **always async**: on a successful spawn it returns
|
|
19
|
+
immediately with the child run id, and the parent keeps working while the child
|
|
20
|
+
runs. When a child settles, the parent is notified in its loop, and it reads
|
|
21
|
+
the child's status and captured outputs on demand with the companion
|
|
22
|
+
`subagent_result` tool.
|
|
23
|
+
|
|
24
|
+
Children inherit the parent's vaulted BYOK provider keys server-side — the
|
|
25
|
+
child submission carries no secrets. Include a provider key for every provider
|
|
26
|
+
your subagents may use when you open the parent session (a parent holding no
|
|
27
|
+
key for the child's provider gets a clear `parent_missing_provider_key` tool
|
|
28
|
+
error). See [Credentials](../credentials.md).
|
|
29
|
+
|
|
30
|
+
## Depth and breadth limits
|
|
31
|
+
|
|
32
|
+
Delegation is bounded by two server-enforced lineage limits:
|
|
33
|
+
|
|
34
|
+
| Limit | Value | Behavior at the limit |
|
|
35
|
+
| --- | --- | --- |
|
|
36
|
+
| Max depth | **5** — the root run is depth 0 and may spawn down to depth 5; a depth-5 run may not spawn further | The spawn is rejected with a `depth_exceeded` tool error (the parent keeps running). |
|
|
37
|
+
| Concurrent children per lineage root | **1000** live (non-terminal) descendants by default; hard platform ceiling **4096** | Further spawns are refused until a child settles. |
|
|
38
|
+
|
|
39
|
+
The whole descendant subtree of one root shares a single depth and breadth
|
|
40
|
+
budget, enforced server-side at every level — a grandchild spawn counts against
|
|
41
|
+
the same root budget as a direct child. Values are mirrored in
|
|
42
|
+
[Limits & quotas](../limits-and-quotas.md).
|
|
43
|
+
|
|
44
|
+
## Where children run: `in-process` vs `container`
|
|
45
|
+
|
|
46
|
+
By default a child runs **in-process**: it executes as a sibling agent process
|
|
47
|
+
inside the parent's own machine, sharing the parent's CPU, memory, and
|
|
48
|
+
lifetime. This is the platform default shipped today.
|
|
49
|
+
|
|
50
|
+
- **No extra runtime cost.** The parent's machine is the billable unit, so
|
|
51
|
+
in-process children bill **$0 of additional runtime** — fan-out is priced by
|
|
52
|
+
the parent box, however many children it hosts. (Model-token spend is still
|
|
53
|
+
whatever each child's provider calls cost on your BYOK key.)
|
|
54
|
+
- **Shared capacity.** N children share the parent's fixed CPU/memory. For
|
|
55
|
+
large fan-outs, size the parent up (`runtime`) rather than assuming each
|
|
56
|
+
child gets its own machine.
|
|
57
|
+
- **Joined lifecycle.** The parent's terminal waits for its in-process children,
|
|
58
|
+
and their results are folded into the parent's per-child accounting. Platform
|
|
59
|
+
recovery re-spawns in-process children exactly once if the parent's machine
|
|
60
|
+
is replaced mid-run — settled children are never re-run.
|
|
61
|
+
|
|
62
|
+
The escape valve is `host: "container"`: the child is dispatched to its **own
|
|
63
|
+
isolated machine** with its own runtime size and its own runtime billing, and
|
|
64
|
+
the parent does not host it. Use it when a child needs guaranteed capacity,
|
|
65
|
+
isolation from the parent's filesystem/CPU, or a different machine size than
|
|
66
|
+
the parent can share.
|
|
67
|
+
|
|
68
|
+
## Lineage and observability
|
|
69
|
+
|
|
70
|
+
Every child — in-process or container — is a first-class run record:
|
|
71
|
+
|
|
72
|
+
- The parent's transcript logs each spawn with the child's run id.
|
|
73
|
+
- Each child has its own status, typed event timeline, and captured outputs.
|
|
74
|
+
The child's events and outputs are readable by id
|
|
75
|
+
(`aex.sessions.outputs(id)` in the SDK, or the CLI's `aex events` /
|
|
76
|
+
`aex outputs`). Child runs are not served by the session read surface
|
|
77
|
+
today — `aex.sessions.get(id)` / `aex sessions` / the CLI's `aex status`
|
|
78
|
+
answer `not_found` for a child id.
|
|
79
|
+
- The child's outputs are handed back to the parent via `subagent_result`, and
|
|
80
|
+
they remain independently downloadable after the lineage finishes.
|
|
81
|
+
|
|
82
|
+
## Bounding delegation
|
|
83
|
+
|
|
84
|
+
- Turn delegation off for a run by cherry-picking builtins without `subagent`
|
|
85
|
+
(see [Agent tools](agent-tools.md)) or setting `includeBuiltinTools: false`.
|
|
86
|
+
- A per-session spend cap (`overrides.maxSpendUsd`) bounds the parent's spend.
|
|
87
|
+
- The depth/breadth limits above are platform defaults and are not settable
|
|
88
|
+
per-session today.
|