@aexhq/sdk 0.13.6
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/LICENSE +201 -0
- package/README.md +160 -0
- package/dist/_contracts/connection-ticket.d.ts +21 -0
- package/dist/_contracts/connection-ticket.js +49 -0
- package/dist/_contracts/event-envelope.d.ts +276 -0
- package/dist/_contracts/event-envelope.js +324 -0
- package/dist/_contracts/event-stream-client.d.ts +47 -0
- package/dist/_contracts/event-stream-client.js +141 -0
- package/dist/_contracts/http.d.ts +35 -0
- package/dist/_contracts/http.js +114 -0
- package/dist/_contracts/index.d.ts +28 -0
- package/dist/_contracts/index.js +29 -0
- package/dist/_contracts/managed-key.d.ts +74 -0
- package/dist/_contracts/managed-key.js +110 -0
- package/dist/_contracts/operations.d.ts +237 -0
- package/dist/_contracts/operations.js +632 -0
- package/dist/_contracts/provider-support.d.ts +220 -0
- package/dist/_contracts/provider-support.js +90 -0
- package/dist/_contracts/proxy-protocol.d.ts +257 -0
- package/dist/_contracts/proxy-protocol.js +234 -0
- package/dist/_contracts/proxy-validation.d.ts +19 -0
- package/dist/_contracts/proxy-validation.js +51 -0
- package/dist/_contracts/run-artifacts.d.ts +47 -0
- package/dist/_contracts/run-artifacts.js +101 -0
- package/dist/_contracts/run-config.d.ts +304 -0
- package/dist/_contracts/run-config.js +659 -0
- package/dist/_contracts/run-cost.d.ts +125 -0
- package/dist/_contracts/run-cost.js +616 -0
- package/dist/_contracts/run-custody.d.ts +226 -0
- package/dist/_contracts/run-custody.js +465 -0
- package/dist/_contracts/run-record.d.ts +127 -0
- package/dist/_contracts/run-record.js +177 -0
- package/dist/_contracts/run-retention.d.ts +213 -0
- package/dist/_contracts/run-retention.js +484 -0
- package/dist/_contracts/run-unit.d.ts +194 -0
- package/dist/_contracts/run-unit.js +215 -0
- package/dist/_contracts/runner-event.d.ts +114 -0
- package/dist/_contracts/runner-event.js +187 -0
- package/dist/_contracts/runtime-manifest.d.ts +106 -0
- package/dist/_contracts/runtime-manifest.js +98 -0
- package/dist/_contracts/runtime-security-profile.d.ts +27 -0
- package/dist/_contracts/runtime-security-profile.js +82 -0
- package/dist/_contracts/runtime-sizes.d.ts +144 -0
- package/dist/_contracts/runtime-sizes.js +136 -0
- package/dist/_contracts/runtime-types.d.ts +212 -0
- package/dist/_contracts/runtime-types.js +2 -0
- package/dist/_contracts/sdk-errors.d.ts +34 -0
- package/dist/_contracts/sdk-errors.js +52 -0
- package/dist/_contracts/sdk-secrets.d.ts +31 -0
- package/dist/_contracts/sdk-secrets.js +220 -0
- package/dist/_contracts/side-effect-audit.d.ts +129 -0
- package/dist/_contracts/side-effect-audit.js +494 -0
- package/dist/_contracts/sse.d.ts +74 -0
- package/dist/_contracts/sse.js +0 -0
- package/dist/_contracts/stable.d.ts +26 -0
- package/dist/_contracts/stable.js +44 -0
- package/dist/_contracts/status.d.ts +19 -0
- package/dist/_contracts/status.js +61 -0
- package/dist/_contracts/submission.d.ts +383 -0
- package/dist/_contracts/submission.js +1380 -0
- package/dist/agents-md.d.ts +46 -0
- package/dist/agents-md.js +83 -0
- package/dist/agents-md.js.map +1 -0
- package/dist/asset-upload.d.ts +66 -0
- package/dist/asset-upload.js +168 -0
- package/dist/asset-upload.js.map +1 -0
- package/dist/bundle.d.ts +33 -0
- package/dist/bundle.js +89 -0
- package/dist/bundle.js.map +1 -0
- package/dist/cli.mjs +4140 -0
- package/dist/cli.mjs.sha256 +1 -0
- package/dist/client.d.ts +460 -0
- package/dist/client.js +857 -0
- package/dist/client.js.map +1 -0
- package/dist/fetch-archive.d.ts +16 -0
- package/dist/fetch-archive.js +170 -0
- package/dist/fetch-archive.js.map +1 -0
- package/dist/file.d.ts +57 -0
- package/dist/file.js +153 -0
- package/dist/file.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server.d.ts +84 -0
- package/dist/mcp-server.js +114 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/node-fs.d.ts +12 -0
- package/dist/node-fs.js +44 -0
- package/dist/node-fs.js.map +1 -0
- package/dist/proxy-endpoint.d.ts +131 -0
- package/dist/proxy-endpoint.js +147 -0
- package/dist/proxy-endpoint.js.map +1 -0
- package/dist/skill.d.ts +117 -0
- package/dist/skill.js +169 -0
- package/dist/skill.js.map +1 -0
- package/dist/version.d.ts +9 -0
- package/dist/version.js +10 -0
- package/dist/version.js.map +1 -0
- package/docs/cleanup.md +38 -0
- package/docs/credentials.md +153 -0
- package/docs/events.md +76 -0
- package/docs/mcp.md +47 -0
- package/docs/outputs.md +157 -0
- package/docs/product-boundaries.md +57 -0
- package/docs/provider-runtime-capabilities.md +103 -0
- package/docs/quickstart.md +110 -0
- package/docs/release.md +99 -0
- package/docs/run-config.md +53 -0
- package/docs/run-record.md +39 -0
- package/docs/skills.md +139 -0
- package/docs/testing.md +29 -0
- package/package.json +47 -0
package/docs/outputs.md
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Outputs
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Outputs
|
|
6
|
+
|
|
7
|
+
Every run produces durable metadata (status, events, snapshots, cleanup state) and an outputs namespace. By default, managed runs capture every regular file the run creates or modifies in the container: the runner snapshots the filesystem just before the agent starts, rescans it when the agent exits, and uploads the delta. There is no default or official output directory. Use `outputs.allowedDirs` only when you want to narrow capture to specific roots, and `outputs.deniedDirs` to subtract noise. `client.download(runId)` returns the whole run — metadata, events, logs, and captured output bytes — as a zip; the per-namespace verbs (`downloadOutputs` / `downloadLogs` / `downloadEvents` / `downloadMetadata`) return one slice each.
|
|
8
|
+
|
|
9
|
+
## Quickstart
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
const runId = await client.submitRun({
|
|
13
|
+
model: "claude-haiku-4-5",
|
|
14
|
+
prompt: "Produce a report and save it as a file.",
|
|
15
|
+
secrets: { anthropic: { apiKey } }
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
await client.wait(runId);
|
|
19
|
+
await client.download(runId, { to: "./run.zip" });
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
aex download <run-id> --out ./run.zip --api-token …
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## The four namespaces
|
|
27
|
+
|
|
28
|
+
A run's downloadable content is organised into four logical namespaces, each with a matching verb. Every zip is assembled **client-side** from the public read endpoints (`getRun` + `listEvents` + `listOutputs` + per-output `/download`) — there is no server-side archive route.
|
|
29
|
+
|
|
30
|
+
| Namespace | What it holds | Verb | CLI |
|
|
31
|
+
| --- | --- | --- | --- |
|
|
32
|
+
| `outputs` | The run's real deliverables. | `downloadOutputs(runId)` | `download <id> --only outputs` |
|
|
33
|
+
| `logs` | Platform diagnostics in canonical namespaces: `runtime/`, `host/`, `provider-proxy/`, and `control-plane/`. Stored separately from `outputs`, so deliverables stay deliverables-only. | `downloadLogs(runId)` | `download <id> --only logs` |
|
|
34
|
+
| `events` | Typed events (`events.jsonl`) plus log/full-stream JSONL when the event channel opt-ins are available. | `downloadEvents(runId)` | `download <id> --only events` |
|
|
35
|
+
| `metadata` | The run record (`run.json`). | `downloadMetadata(runId)` | `download <id> --only metadata` |
|
|
36
|
+
|
|
37
|
+
## What `download()` returns
|
|
38
|
+
|
|
39
|
+
`download(runId)` is the **whole-run** verb — it bundles all four namespaces as top-level folders. It is distinct from `downloadOutput(runId, selector)`, which fetches a single file. Layout:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
metadata/run.json # run record (status, runId, timestamps, snapshot)
|
|
43
|
+
metadata/submission.json # public-safe submission snapshot, when available
|
|
44
|
+
metadata/cost.json # public cost telemetry, when available
|
|
45
|
+
events/events.jsonl # typed event-channel records, ordered
|
|
46
|
+
events/logs.jsonl # log-channel records, when available
|
|
47
|
+
events/all.jsonl # full unified stream, when available
|
|
48
|
+
outputs/<name> # one file per deliverable
|
|
49
|
+
logs/<name> # platform diagnostics
|
|
50
|
+
manifest.json # RunRecordManifestV1
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`manifest.json` is the versioned `RunRecordManifestV1` described in [Run record](run-record.md). It carries:
|
|
54
|
+
|
|
55
|
+
| Field | Meaning |
|
|
56
|
+
| --- | --- |
|
|
57
|
+
| `schemaVersion` / `runRecordSchemaVersion` | Manifest and run-record contract versions. |
|
|
58
|
+
| `runId` | The run the zip was assembled for. |
|
|
59
|
+
| `namespaces[]` / `files[]` | Namespace inventory and per-file presence state. Optional submission/cost/event-channel files are marked `present` only when the client assembled actual entries; custody remains `pending` until its writer/read path exists. |
|
|
60
|
+
| `outputs[]` / `logs[]` | `{ id, filename, sizeBytes?, contentType? }` — one row per file successfully written under `outputs/` / `logs/`. |
|
|
61
|
+
| `errors[]` | `{ namespace, id, filename, message }` — per-artifact byte fetches that failed during assembly. Best-effort: a failure records an entry here and is skipped from the tree rather than aborting the whole zip. |
|
|
62
|
+
|
|
63
|
+
The single-namespace verbs return the same per-file bytes at the zip root (e.g. `downloadOutputs(runId)` → `report.txt` + a `manifest.json`; `downloadEvents(runId)` → `events.jsonl` plus optional `logs.jsonl` / `all.jsonl`).
|
|
64
|
+
|
|
65
|
+
## Downloading one output
|
|
66
|
+
|
|
67
|
+
`downloadOutput(runId, selector)` returns a `Uint8Array`. Omit the selector to download the whole outputs namespace as a zip; pass an output from `client.outputs(runId)`, an `{ id }`, or a path selector against the listed `Output.filename` values to download one file:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
const allOutputs = await client.downloadOutput(runId);
|
|
71
|
+
await client.downloadOutput(runId, undefined, { to: "./outputs.zip" });
|
|
72
|
+
|
|
73
|
+
const report = await client.downloadOutput(runId, { path: "reports/report.txt" });
|
|
74
|
+
console.log(new TextDecoder().decode(report));
|
|
75
|
+
|
|
76
|
+
const looseReport = await client.downloadOutput(runId, { path: "report.txt", match: "suffix" });
|
|
77
|
+
console.log(looseReport.byteLength);
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Lifecycle behaviour
|
|
81
|
+
|
|
82
|
+
`download()` works at any run state — it reads whatever the public endpoints currently expose, so the zip reflects the run as of the call:
|
|
83
|
+
|
|
84
|
+
| Run state | Behaviour |
|
|
85
|
+
| --- | --- |
|
|
86
|
+
| `pending` / `queued` / `provisioning` | `metadata/run.json` reflects the early state; `events/` and `outputs/` are typically empty. |
|
|
87
|
+
| `provider_running`, mid-session / `cleaning_up` | Whatever events + outputs have been captured so far. Call again after terminal for the complete set. |
|
|
88
|
+
| `succeeded` / `failed` / `cancelled` / `terminated` | The complete typed event archive + all captured outputs; log/full-stream JSONL are included when the deployed event API serves those channel opt-ins. |
|
|
89
|
+
|
|
90
|
+
## `outputs.allowedDirs` — override capture roots
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
client.submitRun({
|
|
94
|
+
/* ... */,
|
|
95
|
+
outputs: {
|
|
96
|
+
allowedDirs: ["/workspace/reports", "/workspace/state"]
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
When omitted, aex captures the whole filesystem delta. When supplied, `outputs.allowedDirs` is a whitelist that replaces that default with the listed roots. In other words, explicit `outputs.allowedDirs` narrows capture; it does not add paths on top of `/`.
|
|
102
|
+
|
|
103
|
+
Validation:
|
|
104
|
+
|
|
105
|
+
- absolute UNIX paths only (`/...`),
|
|
106
|
+
- no `..` segments, no NUL bytes,
|
|
107
|
+
- maximum 32 entries,
|
|
108
|
+
- maximum 512 bytes per entry.
|
|
109
|
+
|
|
110
|
+
Runtime notes:
|
|
111
|
+
|
|
112
|
+
- The managed runtime captures files by diffing the filesystem against a baseline snapshot taken just before the agent starts. Platform setup files, installed packages, and materialized inputs are already present before the baseline, so they are excluded by timing.
|
|
113
|
+
- If you pass an explicit root that does not exist by terminal time, that root contributes no files.
|
|
114
|
+
|
|
115
|
+
## `outputs.deniedDirs` — subtract noise
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
client.submitRun({
|
|
119
|
+
/* ... */,
|
|
120
|
+
outputs: {
|
|
121
|
+
deniedDirs: ["node_modules", "/var/cache", "*.tmp"]
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
`outputs.deniedDirs` is subtracted from the capture roots. Entries may be an absolute subtree (`/var/cache`), a bare path segment (`node_modules`), or a `*.ext` extension match. Denied entries beat allowed roots. Platform-mandatory excludes, including pseudo-filesystems and secret/platform paths, always apply and cannot be re-included.
|
|
127
|
+
|
|
128
|
+
Mechanism (no platform-magical paths — this is honest):
|
|
129
|
+
|
|
130
|
+
1. The hosted platform materializes the workspace, opens runtime logs, and records a filesystem baseline across the capture roots.
|
|
131
|
+
2. The agent runs normally. There is no extra model turn and no synthetic sync instruction.
|
|
132
|
+
3. When the agent exits, the runner rescans the capture roots and finds files that are new or whose metadata changed.
|
|
133
|
+
4. The runner uploads changed regular files to durable run artifact storage. Diagnostic log paths are routed to `logs`; other paths are routed to `outputs`.
|
|
134
|
+
|
|
135
|
+
Cost: output capture does not add a model turn. The runner pays a filesystem scan and upload cost near the end of the run.
|
|
136
|
+
|
|
137
|
+
Capture notes:
|
|
138
|
+
|
|
139
|
+
- Files over a configured per-file size cap are skipped.
|
|
140
|
+
- Once total file or byte caps are reached, remaining changed files are dropped from upload.
|
|
141
|
+
- Files that vanish between scan and upload are skipped.
|
|
142
|
+
- Upload failures are recorded in runner events/logs. The zip's `manifest.errors[]` only records byte fetches that failed while assembling the download archive.
|
|
143
|
+
|
|
144
|
+
## Runs without explicit `outputs.allowedDirs`
|
|
145
|
+
|
|
146
|
+
Metadata still gets the full treatment. aex captures every regular file the run created or modified outside mandatory platform excludes. A run that produces no files still returns a zip with `run.json`, `events.jsonl`, and an empty `outputs/` directory (manifest `outputs: []`).
|
|
147
|
+
|
|
148
|
+
## Mid-session download semantics
|
|
149
|
+
|
|
150
|
+
Mid-session calls are **best-effort and side-effect-free**: they expose whatever artifacts have already been uploaded. Files written by the agent are normally uploaded near terminal, after the filesystem diff. If you need the full output set, wait for the run to reach terminal status and call `download()` again.
|
|
151
|
+
|
|
152
|
+
## Safety
|
|
153
|
+
|
|
154
|
+
- Filenames are sanitized for cross-platform safety; collisions are disambiguated with a short id suffix before the extension.
|
|
155
|
+
- Downloads stay within the requested local directory.
|
|
156
|
+
- The archive endpoint is workspace-scoped (`outputs:read` scope) and rate-limited (`AEX_RATE_LIMIT_RUN_ARCHIVE_PER_MINUTE`, default 30/min/workspace).
|
|
157
|
+
- `manifest.json` never contains file bytes — only ids, paths, sizes, content types.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Product capabilities and boundaries
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Product capabilities and boundaries
|
|
6
|
+
|
|
7
|
+
aex is the serverless control plane for autonomous agent sessions. It accepts a complete run request, dispatches it to Goose Managed, records ordered events and logs, captures outputs, and exposes auth-gated reads and downloads.
|
|
8
|
+
|
|
9
|
+
aex is not a custom agent loop, a general-purpose sandbox, an interactive approval system, or a provider compliance layer. True self-host and customer-cloud deployment modes are not supported today.
|
|
10
|
+
|
|
11
|
+
Start with the generated [provider/runtime capability matrix](provider-runtime-capabilities.md) for supported providers, runtime routing, and evidence pointers.
|
|
12
|
+
|
|
13
|
+
## Owned by aex today
|
|
14
|
+
|
|
15
|
+
- Run submission, idempotency, status, cancellation, reads, downloads, and workspace auth.
|
|
16
|
+
- Runtime dispatch through Goose Managed, with unsupported runtime selectors rejected at submission.
|
|
17
|
+
- Ordered event/log capture through the per-run coordinator and durable archive.
|
|
18
|
+
- Output capture into the run record, subject to runtime behavior and storage limits.
|
|
19
|
+
- BYOK provider-key custody for a single run, using the top-level `secrets` carrier and terminal cleanup/revocation attempts for aex-controlled references.
|
|
20
|
+
- Named proxy endpoint policy, auth injection, redaction, call budgets, and audit metadata on the aex-owned proxy path.
|
|
21
|
+
- Default cleanup attempts for tracked aex runtime resources.
|
|
22
|
+
|
|
23
|
+
## Boundary matrix
|
|
24
|
+
|
|
25
|
+
| Area | aex-owned behavior | Inherited or customer-owned behavior |
|
|
26
|
+
| --- | --- | --- |
|
|
27
|
+
| Provider and model policy | aex validates the selected provider, injects the run-scoped BYOK credential, and records public-safe runtime events. | Provider retention, training exclusion, zero-retention, HIPAA/BAA, data residency, abuse policy, and pricing are properties of the selected provider account, endpoint, and contract. |
|
|
28
|
+
| Runtime isolation | Goose Managed runs in an isolated managed runtime. aex tracks resources and runs cleanup attempts. | Runtime isolation guarantees belong to the managed runtime provider. |
|
|
29
|
+
| Secrets | Provider keys, MCP credentials, and proxy auth values are supplied inline per run, held in run-scoped custody, excluded from idempotency, and targeted for cleanup/revocation at terminal where aex controls the reference. | Customers choose and rotate their provider keys and MCP/proxy credentials. Provider-side credentials, sessions, and data may have their own retention rules. |
|
|
30
|
+
| MCP servers | aex accepts remote HTTP/SSE MCP servers, validates their declaration, attaches run-scoped credentials, and records access metadata on the aex-controlled edge. | MCP servers are customer-trusted remote systems. aex does not sandbox their downstream behavior or make an untrusted MCP server safe. |
|
|
31
|
+
| Proxy endpoints | The named endpoint proxy enforces declared host/path/method/auth policy and response caps for calls routed through it. | The upstream service's own auth, data handling, side effects, and compliance posture remain with the upstream service and customer. |
|
|
32
|
+
| Outputs and run record | Captured outputs, events, logs, and metadata are stored under the run record and downloaded through auth-gated routes. | Output content is customer content. Storage, deletion, and retention follow the run policy and infrastructure behavior; deletion-proof custody manifests are roadmap work until shipped. |
|
|
33
|
+
| Human review | Runs execute full-auto after submission. Cancellation is available as an abort control. | Required input, approval, and planning happen before submission or after inspecting the completed run record. aex does not pause a run for platform-mediated human approval or interactive clarification. |
|
|
34
|
+
| Agent identity and memory | The durable product primitive is the run record, addressed by run id. | Persistent agent identity, agent profiles, stateful memory, reusable provider sessions, and saved-definition products are out of scope. |
|
|
35
|
+
| Deployment model | The supported product is the hosted aex control plane, plus the SDK and CLI used to submit and inspect runs. | True self-host and customer-cloud deployments are not supported product modes today. Alternate `baseUrl` values are for local, staging, or hosted aex API planes, not a self-host promise. |
|
|
36
|
+
| Cost | BYOK provider-token charges accrue to the customer's provider account. aex can expose run/runtime/output metadata that helps operators reason about usage. | Paid managed-key mode, free trials, billing-grade cost telemetry, public rate cards, margins, and reconciliation are not shipped in the public product unless explicitly documented later. |
|
|
37
|
+
|
|
38
|
+
## Provider and infrastructure policy links
|
|
39
|
+
|
|
40
|
+
Use these links as starting points for the policy areas aex does not own:
|
|
41
|
+
|
|
42
|
+
- Anthropic API data retention policy: <https://platform.claude.com/docs/en/manage-claude/api-and-data-retention>
|
|
43
|
+
- OpenAI API data controls: <https://platform.openai.com/docs/guides/your-data>
|
|
44
|
+
- Mistral privacy and API data handling: <https://docs.mistral.ai/admin/security-access/privacy>
|
|
45
|
+
- Gemini API data handling: <https://ai.google.dev/gemini-api/docs/logs-policy>
|
|
46
|
+
These links do not create aex guarantees. They identify the provider whose current terms and product behavior must be reviewed for a given workload.
|
|
47
|
+
|
|
48
|
+
## Non-goals and unsupported claims
|
|
49
|
+
|
|
50
|
+
Do not describe aex as providing:
|
|
51
|
+
|
|
52
|
+
- true self-host or customer-cloud deployment support;
|
|
53
|
+
- aex does not provide zero retention, HIPAA, BAA, or data-residency guarantees across providers;
|
|
54
|
+
- aex does not provide a free trial or low-cost managed-key mode;
|
|
55
|
+
- a general-purpose sandbox for every runtime and downstream MCP service;
|
|
56
|
+
- human-in-the-loop approval checkpoints, ask-the-user loops, or interactive resume;
|
|
57
|
+
- persistent agent identity, agent profiles, stateful memory, reusable sessions, or saved agent definitions.
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Provider runtime capabilities
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Provider runtime capabilities
|
|
6
|
+
|
|
7
|
+
Generated from `packages/contracts/src/provider-support.ts`; runtime cells are derived through `checkRuntimeSupported` and `selectRuntime` in `packages/contracts/src/submission.ts`.
|
|
8
|
+
|
|
9
|
+
Regenerate with `pnpm capabilities:generate`; check with `pnpm capabilities:check`.
|
|
10
|
+
|
|
11
|
+
Providers: [Anthropic](#anthropic) (`anthropic`), [DeepSeek](#deepseek) (`deepseek`), [OpenAI](#openai) (`openai`), [Gemini](#gemini) (`gemini`), [Mistral](#mistral) (`mistral`). Runtime selectors: `managed`.
|
|
12
|
+
|
|
13
|
+
All new submissions run on the managed runtime. Public support facts are listed separately from runtime dispatch facts.
|
|
14
|
+
|
|
15
|
+
Status vocabulary: `supported`, `live-unverified`, `rejected`.
|
|
16
|
+
|
|
17
|
+
## Public support
|
|
18
|
+
|
|
19
|
+
| Provider | Wire value | Status | Docs | Evidence |
|
|
20
|
+
| --- | --- | --- | --- | --- |
|
|
21
|
+
| [Anthropic](#anthropic) | `anthropic` | supported | [Credentials](credentials.md); [Events](events.md) | [Submission parser and routing parity](../../contracts/test/submission.test.ts); [Runtime support validator](../../contracts/test/runtime-support.test.ts); [Generated matrix freshness](../../../scripts/validate/capability-matrix.test.ts); [Installed-SDK live user matrix](../../../apps/user-tests/test/live/live-sdk-comprehensive.test.ts); [Runtime support validator](../../contracts/test/runtime-support.test.ts) |
|
|
22
|
+
| [DeepSeek](#deepseek) | `deepseek` | supported | [Credentials](credentials.md); [Events](events.md) | [Submission parser and routing parity](../../contracts/test/submission.test.ts); [Runtime support validator](../../contracts/test/runtime-support.test.ts); [Generated matrix freshness](../../../scripts/validate/capability-matrix.test.ts); [Installed-SDK live user matrix](../../../apps/user-tests/test/live/live-sdk-comprehensive.test.ts); [Runtime support validator](../../contracts/test/runtime-support.test.ts) |
|
|
23
|
+
| [OpenAI](#openai) | `openai` | live-unverified | [Credentials](credentials.md); [Events](events.md) | [Submission parser and routing parity](../../contracts/test/submission.test.ts); [Runtime support validator](../../contracts/test/runtime-support.test.ts); [Generated matrix freshness](../../../scripts/validate/capability-matrix.test.ts) |
|
|
24
|
+
| [Gemini](#gemini) | `gemini` | live-unverified | [Credentials](credentials.md); [Events](events.md) | [Submission parser and routing parity](../../contracts/test/submission.test.ts); [Runtime support validator](../../contracts/test/runtime-support.test.ts); [Generated matrix freshness](../../../scripts/validate/capability-matrix.test.ts) |
|
|
25
|
+
| [Mistral](#mistral) | `mistral` | live-unverified | [Credentials](credentials.md); [Events](events.md) | [Submission parser and routing parity](../../contracts/test/submission.test.ts); [Runtime support validator](../../contracts/test/runtime-support.test.ts); [Generated matrix freshness](../../../scripts/validate/capability-matrix.test.ts) |
|
|
26
|
+
|
|
27
|
+
## Runtime routing
|
|
28
|
+
|
|
29
|
+
| Provider | Default provider | Auto route | `runtime: "managed"` |
|
|
30
|
+
| --- | --- | --- | --- |
|
|
31
|
+
| `anthropic` | yes | `managed` | [supported](#anthropic) |
|
|
32
|
+
| `deepseek` | no | `managed` | [supported](#deepseek) |
|
|
33
|
+
| `openai` | no | `managed` | [live-unverified](#openai) |
|
|
34
|
+
| `gemini` | no | `managed` | [live-unverified](#gemini) |
|
|
35
|
+
| `mistral` | no | `managed` | [live-unverified](#mistral) |
|
|
36
|
+
|
|
37
|
+
## Runtime cell evidence
|
|
38
|
+
|
|
39
|
+
| Provider | Runtime | Status | Ownership | Enforcement path | Evidence |
|
|
40
|
+
| --- | --- | --- | --- | --- | --- |
|
|
41
|
+
| `anthropic` | `managed` | supported | supported | submission parser + managed dispatch | [Installed-SDK live user matrix](../../../apps/user-tests/test/live/live-sdk-comprehensive.test.ts); [Runtime support validator](../../contracts/test/runtime-support.test.ts) |
|
|
42
|
+
| `deepseek` | `managed` | supported | supported | submission parser + managed dispatch | [Installed-SDK live user matrix](../../../apps/user-tests/test/live/live-sdk-comprehensive.test.ts); [Runtime support validator](../../contracts/test/runtime-support.test.ts) |
|
|
43
|
+
| `openai` | `managed` | live-unverified | live-unverified | submission parser + managed dispatch | [Submission parser and routing parity](../../contracts/test/submission.test.ts); [Runtime support validator](../../contracts/test/runtime-support.test.ts); [Generated matrix freshness](../../../scripts/validate/capability-matrix.test.ts) |
|
|
44
|
+
| `gemini` | `managed` | live-unverified | live-unverified | submission parser + managed dispatch | [Submission parser and routing parity](../../contracts/test/submission.test.ts); [Runtime support validator](../../contracts/test/runtime-support.test.ts); [Generated matrix freshness](../../../scripts/validate/capability-matrix.test.ts) |
|
|
45
|
+
| `mistral` | `managed` | live-unverified | live-unverified | submission parser + managed dispatch | [Submission parser and routing parity](../../contracts/test/submission.test.ts); [Runtime support validator](../../contracts/test/runtime-support.test.ts); [Generated matrix freshness](../../../scripts/validate/capability-matrix.test.ts) |
|
|
46
|
+
|
|
47
|
+
## Validation errors
|
|
48
|
+
|
|
49
|
+
| Code | Docs anchor | Enforcement path | Evidence |
|
|
50
|
+
| --- | --- | --- | --- |
|
|
51
|
+
| `feature_runtime_mismatch` | [managed-unsupported-features](#managed-unsupported-features) | collectManagedUnsupportedFeatures + selectRuntime | [Submission parser and routing parity](../../contracts/test/submission.test.ts) |
|
|
52
|
+
|
|
53
|
+
### Managed unsupported features
|
|
54
|
+
|
|
55
|
+
Provider-hosted skill refs such as `Skill.provider(...)` are rejected because new runs dispatch to Goose Managed. Use inline aex skills or remove the provider-hosted ref.
|
|
56
|
+
|
|
57
|
+
Notes:
|
|
58
|
+
|
|
59
|
+
- Public status describes provider availability on the SDK surface. Runtime routing describes how a validated submission is dispatched.
|
|
60
|
+
- `runtime: "native"` is not a runtime selector; the submission parser rejects it as an invalid enum value.
|
|
61
|
+
- `live-unverified` means the shape is accepted by code but does not yet have equal live user-test evidence.
|
|
62
|
+
|
|
63
|
+
## Provider anchors
|
|
64
|
+
|
|
65
|
+
### Anthropic
|
|
66
|
+
|
|
67
|
+
- Wire provider: `anthropic`
|
|
68
|
+
- Public status: supported
|
|
69
|
+
- Auto route: `managed`
|
|
70
|
+
- Docs: [Credentials](credentials.md); [Events](events.md)
|
|
71
|
+
- Evidence: [Submission parser and routing parity](../../contracts/test/submission.test.ts); [Runtime support validator](../../contracts/test/runtime-support.test.ts); [Generated matrix freshness](../../../scripts/validate/capability-matrix.test.ts); [Installed-SDK live user matrix](../../../apps/user-tests/test/live/live-sdk-comprehensive.test.ts); [Runtime support validator](../../contracts/test/runtime-support.test.ts)
|
|
72
|
+
|
|
73
|
+
### DeepSeek
|
|
74
|
+
|
|
75
|
+
- Wire provider: `deepseek`
|
|
76
|
+
- Public status: supported
|
|
77
|
+
- Auto route: `managed`
|
|
78
|
+
- Docs: [Credentials](credentials.md); [Events](events.md)
|
|
79
|
+
- Evidence: [Submission parser and routing parity](../../contracts/test/submission.test.ts); [Runtime support validator](../../contracts/test/runtime-support.test.ts); [Generated matrix freshness](../../../scripts/validate/capability-matrix.test.ts); [Installed-SDK live user matrix](../../../apps/user-tests/test/live/live-sdk-comprehensive.test.ts); [Runtime support validator](../../contracts/test/runtime-support.test.ts)
|
|
80
|
+
|
|
81
|
+
### OpenAI
|
|
82
|
+
|
|
83
|
+
- Wire provider: `openai`
|
|
84
|
+
- Public status: live-unverified
|
|
85
|
+
- Auto route: `managed`
|
|
86
|
+
- Docs: [Credentials](credentials.md); [Events](events.md)
|
|
87
|
+
- Evidence: [Submission parser and routing parity](../../contracts/test/submission.test.ts); [Runtime support validator](../../contracts/test/runtime-support.test.ts); [Generated matrix freshness](../../../scripts/validate/capability-matrix.test.ts)
|
|
88
|
+
|
|
89
|
+
### Gemini
|
|
90
|
+
|
|
91
|
+
- Wire provider: `gemini`
|
|
92
|
+
- Public status: live-unverified
|
|
93
|
+
- Auto route: `managed`
|
|
94
|
+
- Docs: [Credentials](credentials.md); [Events](events.md)
|
|
95
|
+
- Evidence: [Submission parser and routing parity](../../contracts/test/submission.test.ts); [Runtime support validator](../../contracts/test/runtime-support.test.ts); [Generated matrix freshness](../../../scripts/validate/capability-matrix.test.ts)
|
|
96
|
+
|
|
97
|
+
### Mistral
|
|
98
|
+
|
|
99
|
+
- Wire provider: `mistral`
|
|
100
|
+
- Public status: live-unverified
|
|
101
|
+
- Auto route: `managed`
|
|
102
|
+
- Docs: [Credentials](credentials.md); [Events](events.md)
|
|
103
|
+
- Evidence: [Submission parser and routing parity](../../contracts/test/submission.test.ts); [Runtime support validator](../../contracts/test/runtime-support.test.ts); [Generated matrix freshness](../../../scripts/validate/capability-matrix.test.ts)
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: aex quickstart
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Quickstart
|
|
6
|
+
|
|
7
|
+
1. Get an aex SDK API token (`ant_…`).
|
|
8
|
+
2. Create `AexClient` — the workspace is derived server-side from the token.
|
|
9
|
+
3. Submit the run with the agent's brief plus an inline `secrets` bundle. Wait for terminal status. Fetch outputs.
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { AexClient } from "@aexhq/sdk";
|
|
13
|
+
|
|
14
|
+
const client = new AexClient({
|
|
15
|
+
apiToken: process.env.AEX_API_TOKEN!
|
|
16
|
+
// baseUrl defaults to https://api.aex.dev - set it for local or staging planes.
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const runId = await client.submitRun({
|
|
20
|
+
model: "claude-haiku-4-5",
|
|
21
|
+
prompt: "Write a short answer about agent-first SDK design.",
|
|
22
|
+
secrets: { anthropic: { apiKey: process.env.ANTHROPIC_API_KEY! } }
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const run = await client.wait(runId);
|
|
26
|
+
console.log(run.status);
|
|
27
|
+
console.log(await client.outputs(runId));
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
For reusable, credential-free configs, use an ordinary function:
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
function summarise(topic: string) {
|
|
34
|
+
return {
|
|
35
|
+
model: "claude-haiku-4-5",
|
|
36
|
+
prompt: `Write a short answer about ${topic}.`
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const runId = await client.submitRun({
|
|
41
|
+
...summarise("agent-first SDK design"),
|
|
42
|
+
secrets: { anthropic: { apiKey: process.env.ANTHROPIC_API_KEY! } }
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Or from the shell:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
aex run \
|
|
50
|
+
--api-token "$AEX_API_TOKEN" \
|
|
51
|
+
--anthropic-api-key "$ANTHROPIC_API_KEY" \
|
|
52
|
+
--model claude-haiku-4-5 \
|
|
53
|
+
--prompt "Write a short answer about agent-first SDK design." \
|
|
54
|
+
--follow
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
For a config-file flow, pass `--config <path>` with a run-config JSON file for a single run request (`{ model, system?, prompt, skills?, mcpServers?, environment?, proxyEndpoints?, metadata? }`). Both surfaces hit the same aex backend and operate on the same durable run records — pick whichever is most convenient.
|
|
58
|
+
|
|
59
|
+
## Where things go: customer → primitive mapping
|
|
60
|
+
|
|
61
|
+
Every kind of thing you want to ship at run time has exactly one right primitive in the SDK. Reach for the right one rather than rolling your own wrapper.
|
|
62
|
+
|
|
63
|
+
| What you have | Primitive | What it does |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| Non-secret paths or config (`BROLL_STORE`, mode flags) | `environment.envVars` | Mounted as `RUNTIME.env` / `RUNTIME.json`; `__KEY__` substitution in agent-facing markdown; echoed back as `run.runtimeManifest.envVars` |
|
|
66
|
+
| Upstream HTTPS API keys (TMDB, Brave, Tavily, …) | `ProxyEndpoint` | Credentials live server-side; aex proxy injects them on outbound calls. The key never enters the container. |
|
|
67
|
+
| MCP server credentials | `secrets.mcpServers` | Anthropic Vault, attached per session |
|
|
68
|
+
| Provider API key | `secrets.<provider>.apiKey` | Required on every `submitRun`; per-run vault entry matching `provider` |
|
|
69
|
+
| Non-secret reference data folders (transcripts, persona docs, PDFs) | `File.fromPath('./customer-folder/')` | Materialized under `/workspace/files/<f_id>/<name>` by default and described in the agent-facing instructions |
|
|
70
|
+
| Executable skill code (a `.pyz` wrapper, scripts, prompts) | `Skill.fromPath('./skills/my-skill/')` | Registered with Anthropic's Skills API; auto-discovered by the agent |
|
|
71
|
+
| Agent instructions file | `AgentsMd.fromPath('./AGENTS.md')` | Prepended as the first user turn |
|
|
72
|
+
|
|
73
|
+
`Skill`, `AgentsMd`, and `File` values are materialized for the run before the first agent turn. `environment.envVars` values surface in runtime metadata and can be referenced by `__KEY__` placeholders in agent-facing markdown.
|
|
74
|
+
|
|
75
|
+
## Safe retries with `idempotencyKey`
|
|
76
|
+
|
|
77
|
+
Every `submitRun` call carries an `idempotencyKey`. When omitted the SDK auto-generates a UUID per call. Supplying your own key makes retries deterministic:
|
|
78
|
+
|
|
79
|
+
| Submit shape | Server response |
|
|
80
|
+
| --- | --- |
|
|
81
|
+
| New `idempotencyKey` | HTTP 202 — returns the new run id. |
|
|
82
|
+
| Same key + identical request body hash | HTTP 200 — returns the original run id. The SDK call resolves with that id. |
|
|
83
|
+
| Same key + **different** request body hash | HTTP 409 — body `{ error: { message, code: "idempotency_conflict", details: { existingRunId } } }`. The SDK throws an `HttpError` carrying that body. Use `details.existingRunId` to adopt the pre-existing run, or pick a fresh key. |
|
|
84
|
+
| Omitted `idempotencyKey` | A new UUID is generated on every call — repeat submissions create new runs. |
|
|
85
|
+
|
|
86
|
+
The request hash is computed server-side over the canonical submission JSON (model, prompt, system, environment, skill refs, MCP server descriptors, proxy endpoints, `outputs`, etc.) so reordering JSON keys, adding whitespace, or rotating the inline secret bundle does **not** change the hash. Changing the prompt, model, system, or any other non-secret field does.
|
|
87
|
+
|
|
88
|
+
Pattern for safe retries:
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
const idempotencyKey = crypto.randomUUID();
|
|
92
|
+
async function submitWithRetry() {
|
|
93
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
94
|
+
try {
|
|
95
|
+
return await client.submitRun({
|
|
96
|
+
model: "claude-haiku-4-5",
|
|
97
|
+
prompt: "...",
|
|
98
|
+
idempotencyKey,
|
|
99
|
+
secrets: { anthropic: { apiKey: process.env.ANTHROPIC_API_KEY! } }
|
|
100
|
+
});
|
|
101
|
+
} catch (err) {
|
|
102
|
+
if (err instanceof Error && err.message.includes("network")) continue;
|
|
103
|
+
throw err;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
throw new Error("submitRun failed after retries");
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The same `idempotencyKey` reused with the same body will deterministically resolve to the same run id regardless of how many times the network drops between attempts. Query, stream, wait, or download the run by that id.
|
package/docs/release.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Release
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Release
|
|
6
|
+
|
|
7
|
+
Releases are manually dispatched from `.github/workflows/release.yml` after the
|
|
8
|
+
target version is already on `main`. The npm package version is the release
|
|
9
|
+
source of truth. The workflow publishes to npm and runs post-publish install
|
|
10
|
+
checks, but it does not create git tags or GitHub Releases, keeping the remote
|
|
11
|
+
repository on a clean `main` branch unless tags are added deliberately later.
|
|
12
|
+
|
|
13
|
+
## How to ship a release
|
|
14
|
+
|
|
15
|
+
1. Bump both `packages/sdk/package.json#version` and
|
|
16
|
+
`packages/sdk/src/version.ts` to the next semver.
|
|
17
|
+
2. Land the change on `main` with any companion code or docs.
|
|
18
|
+
3. Confirm CI is green.
|
|
19
|
+
4. Run the **Release** workflow from `main` and choose the npm dist-tag
|
|
20
|
+
(`latest` or `next`).
|
|
21
|
+
|
|
22
|
+
If `@aexhq/sdk@<version>` already exists on npm, the release workflow fails before
|
|
23
|
+
publishing. A failed release is fixed by bumping to a higher version and running
|
|
24
|
+
the workflow again.
|
|
25
|
+
|
|
26
|
+
## Release pipeline
|
|
27
|
+
|
|
28
|
+
The workflow has two jobs:
|
|
29
|
+
|
|
30
|
+
1. **`publish`** runs on Ubuntu in the protected `npm-release` environment:
|
|
31
|
+
- `pnpm install --frozen-lockfile`
|
|
32
|
+
- npm version availability check for `packages/sdk/package.json#version`
|
|
33
|
+
- `pnpm lint`
|
|
34
|
+
- `pnpm test`
|
|
35
|
+
- `pnpm run docs:build`
|
|
36
|
+
- `pnpm build`
|
|
37
|
+
- `pnpm --filter @aexhq/sdk pack`
|
|
38
|
+
- `pnpm run test:user:offline` against the packed tarball
|
|
39
|
+
- a final npm version availability check
|
|
40
|
+
- `pnpm publish --provenance --no-git-checks --access public`
|
|
41
|
+
2. **`post-publish-user-tests`** waits for npm registry visibility, then runs
|
|
42
|
+
`pnpm run test:user:offline` against the published version on Ubuntu and
|
|
43
|
+
Windows.
|
|
44
|
+
|
|
45
|
+
The pre-publish user-test gate catches broken package shape, missing CLI bin,
|
|
46
|
+
workspace dependency leaks, and TypeScript/ESM install regressions before npm
|
|
47
|
+
publish. The post-publish matrix confirms the published registry artifact is
|
|
48
|
+
installable from clean user projects on both Linux and Windows.
|
|
49
|
+
|
|
50
|
+
## What ships in the tarball
|
|
51
|
+
|
|
52
|
+
The published tarball is **self-contained**. It declares **zero `@aexhq/*`
|
|
53
|
+
runtime dependencies** and is installable from a clean `npm install @aexhq/sdk`
|
|
54
|
+
with no workspace access:
|
|
55
|
+
|
|
56
|
+
- `@aexhq/contracts` lives in `packages/sdk/package.json#devDependencies`
|
|
57
|
+
only. At build time, [`packages/sdk/scripts/inline-contracts.mjs`](../scripts/inline-contracts.mjs)
|
|
58
|
+
copies `packages/contracts/dist/**` into `packages/sdk/dist/_contracts/` and
|
|
59
|
+
rewrites `from "@aexhq/contracts"` to `from "./_contracts/index.js"` across
|
|
60
|
+
the SDK dist tree. A sanity check at the end of that script refuses to finish
|
|
61
|
+
if any bare `@aexhq/contracts` specifier survives.
|
|
62
|
+
- `@aexhq/cli` is bundled at build time by
|
|
63
|
+
[`packages/sdk/scripts/bundle-cli.mjs`](../scripts/bundle-cli.mjs) into a
|
|
64
|
+
single `dist/cli.mjs`, which is the `bin: aex` entry in
|
|
65
|
+
`packages/sdk/package.json`.
|
|
66
|
+
- This invariant is mechanically enforced by
|
|
67
|
+
`apps/user-tests/test/offline/install.test.ts` ("declares no @aexhq/*
|
|
68
|
+
runtime dependencies") before publish.
|
|
69
|
+
|
|
70
|
+
## Repository setup
|
|
71
|
+
|
|
72
|
+
Configure npm Trusted Publishing for this repository:
|
|
73
|
+
|
|
74
|
+
- **Organization or user**: `aexhq`
|
|
75
|
+
- **Repository**: `aex`
|
|
76
|
+
- **Workflow filename**: `release.yml`
|
|
77
|
+
- **Environment name**: `npm-release`
|
|
78
|
+
|
|
79
|
+
Protect the GitHub `npm-release` environment with the reviewers or deployment
|
|
80
|
+
rules you want before enabling real publishes. No `NPM_TOKEN` secret is
|
|
81
|
+
required when Trusted Publishing is configured.
|
|
82
|
+
|
|
83
|
+
## Local checklist
|
|
84
|
+
|
|
85
|
+
Before dispatching a release, the same public-safe checks can be run locally:
|
|
86
|
+
|
|
87
|
+
```text
|
|
88
|
+
pnpm lint
|
|
89
|
+
pnpm test
|
|
90
|
+
pnpm run test:user:offline
|
|
91
|
+
pnpm run docs:build
|
|
92
|
+
pnpm run pack:sdk
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Rollback
|
|
96
|
+
|
|
97
|
+
There is no reliable "unpublish and reuse the version" path. npm version numbers
|
|
98
|
+
are effectively immutable for release purposes, so a bad release is fixed by
|
|
99
|
+
publishing a higher version.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Run configuration
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Run configuration
|
|
6
|
+
|
|
7
|
+
A run config is the credential-free subset of a `submitRun` request that you can keep in code or load from a JSON file. It is not a platform object, saved definition, DSL, trigger, or persistent agent profile. aex only stores the immutable run record created when you submit.
|
|
8
|
+
|
|
9
|
+
Allowed fields:
|
|
10
|
+
|
|
11
|
+
- `model` - required.
|
|
12
|
+
- `prompt` - required, string or array of strings.
|
|
13
|
+
- `system` - optional system message.
|
|
14
|
+
- `skills` - array of `SkillRef`, either workspace, provider, or inline.
|
|
15
|
+
- `mcpServers` - array of `McpServerRef`; headers are split into `secrets.mcpServers` server-side.
|
|
16
|
+
- `proxyEndpoints` - array of `PlatformProxyEndpoint`.
|
|
17
|
+
- `environment` - `{ networking?, packages?, envVars? }`. `envVars` are merged into the in-container `RUNTIME.env` / `RUNTIME.json` mounts.
|
|
18
|
+
- `metadata` - non-secret structured metadata.
|
|
19
|
+
|
|
20
|
+
`agentsMd`, `files`, and `outputs` are top-level `submitRun` options, not run-config fields. They carry bytes or capture behavior that belongs on a concrete run submission.
|
|
21
|
+
|
|
22
|
+
Secrets never live in run config. Pass credentials through `submitRun({ ...config, secrets })` in the SDK or the equivalent host-mode flags (`--anthropic-api-key`, `--mcp-auth`, `--proxy-auth`) in the CLI.
|
|
23
|
+
|
|
24
|
+
## Reuse in code
|
|
25
|
+
|
|
26
|
+
Use an ordinary function when you want reusable typed parameters. aex does not store or execute this function; it only receives the run parameters you submit.
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
function summarise(topic: string) {
|
|
30
|
+
return {
|
|
31
|
+
model: "claude-haiku-4-5",
|
|
32
|
+
system: "You are a concise automation agent.",
|
|
33
|
+
prompt: `Write a short answer about ${topic}.`
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
await client.submitRun({
|
|
38
|
+
...summarise("agent-first SDK design"),
|
|
39
|
+
secrets: { anthropic: { apiKey } }
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## CLI
|
|
44
|
+
|
|
45
|
+
The `aex run` host subcommand accepts the same run config either as a JSON file:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
aex run --config ./run.json \
|
|
49
|
+
--api-token "$AEX_API_TOKEN" \
|
|
50
|
+
--anthropic-api-key "$ANTHROPIC_API_KEY"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
...or as explicit flags (`--model`, `--system`, `--prompt`, `--mcp`, `--mcp-auth`, `--proxy-endpoint`, `--proxy-auth`, `--metadata`). The two modes are mutually exclusive.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Run record
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Run record
|
|
6
|
+
|
|
7
|
+
The run record is the durable product primitive for one run id. It is the public-safe bundle of status metadata, the non-secret submission snapshot when available, typed events, captured outputs, platform diagnostics, and manifest entries for custody and cost telemetry.
|
|
8
|
+
|
|
9
|
+
`client.download(runId)` and `aex download <run-id>` return a zip with this layout:
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
manifest.json
|
|
13
|
+
metadata/run.json
|
|
14
|
+
metadata/submission.json # when a public-safe submission snapshot is returned by the read API
|
|
15
|
+
metadata/cost.json # when public cost telemetry is returned by the read API
|
|
16
|
+
events/events.jsonl
|
|
17
|
+
events/logs.jsonl # when the event API serves channel=log
|
|
18
|
+
events/all.jsonl # when the event API serves channel=all
|
|
19
|
+
outputs/<captured deliverable files>
|
|
20
|
+
logs/<platform diagnostic files>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`manifest.json` is versioned as `RunRecordManifestV1`:
|
|
24
|
+
|
|
25
|
+
| Field | Meaning |
|
|
26
|
+
| --- | --- |
|
|
27
|
+
| `schemaVersion` | `aex.run-record.manifest.v1`. |
|
|
28
|
+
| `runRecordSchemaVersion` | `aex.run-record.v1`. |
|
|
29
|
+
| `runId` | The run the archive was assembled for. |
|
|
30
|
+
| `namespaces[]` | The documented top-level namespaces: `metadata`, `events`, `outputs`, `logs`. |
|
|
31
|
+
| `files[]` | Inventory of expected and present files with `namespace`, `path`, `role`, and `status`. |
|
|
32
|
+
| `outputs[]` / `logs[]` | Compatibility aliases for present captured artifacts. |
|
|
33
|
+
| `errors[]` | Per-artifact byte fetch failures during archive assembly. |
|
|
34
|
+
|
|
35
|
+
Current v1 downloads always include `metadata/run.json` and `events/events.jsonl`. `events/events.jsonl` contains typed event-channel records only; log-channel or full-stream exports are not mixed into that file. The client also probes the existing event API opt-ins and includes `events/logs.jsonl` / `events/all.jsonl` when `?channel=log` / `?channel=all` prove those streams are available. Older deployments that do not serve those channel reads keep the manifest entries as `unavailable`.
|
|
36
|
+
|
|
37
|
+
`metadata/submission.json` is present only when the run read shape includes a public-safe submission snapshot. `metadata/cost.json` is present only when the run read shape includes public `costTelemetry`; otherwise cost stays `pending`. `metadata/custody.json` remains `pending` until the custody manifest writer and public read surface land. `events/manifest.json` remains `unavailable` in this client-side slice because there is no public coordinator-manifest download route.
|
|
38
|
+
|
|
39
|
+
The record boundary is public-safe. It must not contain provider API keys, runner bearers, workspace tokens, signed URLs, raw provider response bodies, R2 object keys, Vault ids, raw query strings, or secret-shaped values. Credentials are supplied per run and vaulted separately for the run lifetime.
|