@amalgm/agents 0.2.0 → 0.2.1
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/PURPOSE.md +27 -25
- package/README.md +46 -19
- package/dist/agents.d.ts +26 -4
- package/dist/agents.js +87 -4
- package/dist/bin/mcp.js +1 -1
- package/dist/cli/help.d.ts +1 -1
- package/dist/cli/help.js +13 -2
- package/dist/cli/open.d.ts +1 -1
- package/dist/cli/open.js +5 -1
- package/dist/cli/run.js +8 -3
- package/dist/cli/session-commands.d.ts +4 -0
- package/dist/cli/session-commands.js +54 -0
- package/dist/drivers.d.ts +4 -0
- package/dist/drivers.js +25 -0
- package/dist/errors.d.ts +1 -1
- package/dist/errors.js +2 -0
- package/dist/event-store.d.ts +13 -0
- package/dist/event-store.js +50 -0
- package/dist/http/server.js +7 -1
- package/dist/http/session-routes.d.ts +2 -0
- package/dist/http/session-routes.js +67 -0
- package/dist/http/stream.d.ts +3 -0
- package/dist/http/stream.js +30 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/mcp/agent-tools.js +1 -1
- package/dist/mcp/session-tools.d.ts +3 -0
- package/dist/mcp/session-tools.js +81 -0
- package/dist/mcp/tools.js +2 -1
- package/dist/messages.d.ts +3 -0
- package/dist/messages.js +56 -0
- package/dist/rows.d.ts +4 -1
- package/dist/rows.js +39 -0
- package/dist/runtime.d.ts +29 -0
- package/dist/runtime.js +176 -0
- package/dist/schema.js +101 -53
- package/dist/session-store.d.ts +15 -0
- package/dist/session-store.js +83 -0
- package/dist/turn-store.d.ts +31 -0
- package/dist/turn-store.js +164 -0
- package/dist/types.d.ts +106 -0
- package/docs/ARCHITECTURE.md +33 -21
- package/docs/CLI.md +43 -3
- package/docs/DATA_MODEL.md +46 -7
- package/docs/DEFINITIONS.md +4 -4
- package/docs/DRIVERS.md +72 -0
- package/docs/ENGINE_INTEGRATION.md +67 -22
- package/docs/MCP.md +19 -3
- package/docs/REST.md +97 -14
- package/docs/SDK.md +61 -12
- package/docs/SECURITY.md +35 -6
- package/examples/basic.ts +22 -8
- package/package.json +5 -5
- package/skills/amalgm-agents/SKILL.md +12 -3
- package/skills/amalgm-agents/agents/openai.yaml +2 -2
package/docs/CLI.md
CHANGED
|
@@ -3,6 +3,18 @@
|
|
|
3
3
|
The CLI prints JSON to stdout and errors to stderr. It shares the SDK database;
|
|
4
4
|
there is no CLI-specific registry.
|
|
5
5
|
|
|
6
|
+
## Global options
|
|
7
|
+
|
|
8
|
+
| Option | Meaning |
|
|
9
|
+
|---|---|
|
|
10
|
+
| `--state-dir <path>` | Override the Agents state directory |
|
|
11
|
+
| `--drivers <a.js,b.js>` | Load compiled driver modules |
|
|
12
|
+
| `--help` | Print command help |
|
|
13
|
+
|
|
14
|
+
`AMALGM_AGENT_DRIVERS` supplies the same comma-separated driver list.
|
|
15
|
+
|
|
16
|
+
## Agent commands
|
|
17
|
+
|
|
6
18
|
```bash
|
|
7
19
|
amalgm-agents agent list [--include-deleted]
|
|
8
20
|
amalgm-agents agent show <id> [--include-deleted]
|
|
@@ -11,11 +23,39 @@ amalgm-agents agent update <id> <patch.json>
|
|
|
11
23
|
amalgm-agents agent delete <id>
|
|
12
24
|
```
|
|
13
25
|
|
|
14
|
-
|
|
26
|
+
`create` requires an unused id. `update` uses the nested PATCH rules in
|
|
27
|
+
[Definitions](./DEFINITIONS.md).
|
|
15
28
|
|
|
16
|
-
|
|
29
|
+
## Session commands
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
amalgm-agents session list [--agent <id>] [--include-archived]
|
|
33
|
+
amalgm-agents session start <agent-id> [--id <id>] [--revision <revision-id>]
|
|
34
|
+
amalgm-agents session show <id>
|
|
35
|
+
amalgm-agents session events <id> [--after <sequence>]
|
|
36
|
+
amalgm-agents session send <id> <message> [--key <idempotency-key>]
|
|
37
|
+
amalgm-agents session cancel <id>
|
|
38
|
+
amalgm-agents session archive <id>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`session show` returns the session, turns, and event ledger together.
|
|
42
|
+
|
|
43
|
+
## Talk shortcut
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
amalgm-agents talk <agent-id> <message> \
|
|
47
|
+
[--session <session-id>] [--key <idempotency-key>] [--background]
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Without `--session`, the command starts one. Foreground waits for a terminal
|
|
51
|
+
turn; background returns the accepted turn immediately.
|
|
52
|
+
|
|
53
|
+
## Servers
|
|
17
54
|
|
|
18
55
|
```bash
|
|
19
56
|
amalgm-agents-rest --host 127.0.0.1 --port 4317 --token "$TOKEN"
|
|
20
|
-
amalgm-agents-mcp --state-dir ./state
|
|
57
|
+
amalgm-agents-mcp --state-dir ./state --drivers ./dist/driver.js
|
|
21
58
|
```
|
|
59
|
+
|
|
60
|
+
The REST CLI binds loopback by default. Use a bearer token before deliberately
|
|
61
|
+
binding to any shared interface.
|
package/docs/DATA_MODEL.md
CHANGED
|
@@ -1,17 +1,56 @@
|
|
|
1
|
-
# Persistence
|
|
1
|
+
# Persistence and recovery
|
|
2
2
|
|
|
3
3
|
The default database is `agents.db` inside the state directory resolved by
|
|
4
|
-
`@amalgm/core/identity`: `
|
|
5
|
-
`$
|
|
4
|
+
`@amalgm/core/identity`: `AMALGM_AGENTS_DIR` verbatim when set, otherwise
|
|
5
|
+
`$AMALGM_DIR/agents`, otherwise the scoped layout
|
|
6
|
+
`~/.amalgm/users/local/agents`. Set `stateDir` or `databasePath` to relocate
|
|
7
|
+
it directly.
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
## Tables
|
|
8
10
|
|
|
9
11
|
| Table | Role |
|
|
10
12
|
|---|---|
|
|
11
13
|
| `agents` | stable identity, current revision pointer, tombstone |
|
|
12
14
|
| `agent_revisions` | immutable normalized definitions |
|
|
15
|
+
| `sessions` | pinned revision and opaque driver session id |
|
|
16
|
+
| `turns` | accepted input and execution outcome |
|
|
17
|
+
| `session_events` | ordered append-only execution observations |
|
|
18
|
+
|
|
19
|
+
Foreign keys prevent orphan sessions, turns, and events. SQLite WAL mode and a
|
|
20
|
+
five-second busy timeout support multiple read-oriented surfaces while one
|
|
21
|
+
service owns mutations.
|
|
13
22
|
|
|
14
23
|
Repeating the current definition is idempotent. Returning to content used by
|
|
15
|
-
an earlier revision creates a new revision number
|
|
16
|
-
|
|
17
|
-
|
|
24
|
+
an earlier revision creates a new revision number so the definition timeline
|
|
25
|
+
remains complete and append-only.
|
|
26
|
+
|
|
27
|
+
## Turn states
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
queued → running → completed
|
|
31
|
+
├──→ failed
|
|
32
|
+
├──→ cancelling → cancelled
|
|
33
|
+
└──→ interrupted
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`queued`, `running`, and `cancelling` are non-terminal. At service startup they
|
|
37
|
+
become `interrupted`, because the previous process may have completed external
|
|
38
|
+
side effects before dying. The service never guesses and never automatically
|
|
39
|
+
replays uncertain work.
|
|
40
|
+
|
|
41
|
+
## Idempotency
|
|
42
|
+
|
|
43
|
+
`idempotencyKey` is unique within a session. Repeating a key returns its
|
|
44
|
+
existing turn and does not invoke the driver again. Callers should derive it
|
|
45
|
+
from their durable request identity instead of generating a new value on every
|
|
46
|
+
retry.
|
|
47
|
+
|
|
48
|
+
## Events
|
|
49
|
+
|
|
50
|
+
Every event receives the next integer sequence within its session. SSE first
|
|
51
|
+
reads committed events after the requested sequence, then subscribes to newly
|
|
52
|
+
committed events. Reconnecting with the last SSE id therefore closes the gap
|
|
53
|
+
without polling or losing events.
|
|
54
|
+
|
|
55
|
+
Events are facts, not mutable projections. User interfaces derive streaming
|
|
56
|
+
text, messages, tool activity, and status from the ledger.
|
package/docs/DEFINITIONS.md
CHANGED
|
@@ -37,13 +37,13 @@ products.
|
|
|
37
37
|
|
|
38
38
|
`id` is a stable machine identity: 1–128 lowercase letters, numbers, dots,
|
|
39
39
|
underscores, or hyphens. Renaming `name` never changes it. Deleted ids remain
|
|
40
|
-
reserved so
|
|
40
|
+
reserved so historical sessions cannot be confused with a new agent.
|
|
41
41
|
|
|
42
42
|
## Revisions
|
|
43
43
|
|
|
44
44
|
The normalized complete definition is hashed. An edit with equal content keeps
|
|
45
45
|
the current revision. Any changed field creates a new immutable revision.
|
|
46
|
-
|
|
46
|
+
Sessions always retain the revision selected at creation.
|
|
47
47
|
|
|
48
48
|
## PATCH behavior
|
|
49
49
|
|
|
@@ -61,5 +61,5 @@ authoritative and de-duplicated. Set nullable fields such as `model` or
|
|
|
61
61
|
- `resources.skills` and `resources.files` are resolved by the host.
|
|
62
62
|
- `resources.subagents` describes intended relationships; the host still
|
|
63
63
|
authorizes every agent-to-agent call.
|
|
64
|
-
- `driver.config` is non-secret
|
|
65
|
-
|
|
64
|
+
- `driver.config` is non-secret runtime configuration interpreted only by the
|
|
65
|
+
selected driver.
|
package/docs/DRIVERS.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Agent drivers
|
|
2
|
+
|
|
3
|
+
Drivers connect durable Agents state to a native or hosted runtime. They are
|
|
4
|
+
registered by the embedding process and selected by `definition.driver.id`.
|
|
5
|
+
|
|
6
|
+
```ts
|
|
7
|
+
import { defineDriver } from '@amalgm/agents';
|
|
8
|
+
|
|
9
|
+
export default defineDriver({
|
|
10
|
+
id: 'my-runtime',
|
|
11
|
+
async run(request, context) {
|
|
12
|
+
context.signal.throwIfAborted();
|
|
13
|
+
context.emit({ type: 'text.delta', data: { text: 'Working…' } });
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
driverSessionId: request.driverSessionId ?? 'native-session-id',
|
|
17
|
+
message: {
|
|
18
|
+
role: 'assistant',
|
|
19
|
+
parts: [{ type: 'text', text: 'Done.' }],
|
|
20
|
+
},
|
|
21
|
+
metadata: { provider: 'example' },
|
|
22
|
+
};
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Request
|
|
28
|
+
|
|
29
|
+
`DriverRunRequest` includes:
|
|
30
|
+
|
|
31
|
+
- the immutable `AgentRevision`;
|
|
32
|
+
- the durable session and current turn;
|
|
33
|
+
- ordered completed history before this turn;
|
|
34
|
+
- the accepted input; and
|
|
35
|
+
- the opaque `driverSessionId` returned by an earlier turn.
|
|
36
|
+
|
|
37
|
+
Drivers do not receive a database handle. They resolve Toolbox actions,
|
|
38
|
+
credentials, skills, files, and native processes through dependencies supplied
|
|
39
|
+
by their host.
|
|
40
|
+
|
|
41
|
+
## Events and results
|
|
42
|
+
|
|
43
|
+
Call `context.emit` for streaming or structured observations. The event is
|
|
44
|
+
committed before the call returns. Use type `message` with an assistant
|
|
45
|
+
`AgentMessage` for a durable output message; other event names are driver-owned
|
|
46
|
+
and their data must be JSON.
|
|
47
|
+
|
|
48
|
+
A final returned `message` is appended once before turn completion. Returned
|
|
49
|
+
`driverSessionId` replaces the prior opaque value for future continuation.
|
|
50
|
+
|
|
51
|
+
## Cancellation and limits
|
|
52
|
+
|
|
53
|
+
Drivers must observe `context.signal` and stop their underlying process or
|
|
54
|
+
request. The service records cancellation intent before aborting the signal.
|
|
55
|
+
Input and event sizes are bounded. A driver that emits invalid or oversized
|
|
56
|
+
data fails the turn explicitly.
|
|
57
|
+
|
|
58
|
+
The in-process boundary cannot forcibly kill an uncooperative driver. Process
|
|
59
|
+
drivers should own their child process and terminate it when signalled.
|
|
60
|
+
|
|
61
|
+
## Loading drivers in CLIs
|
|
62
|
+
|
|
63
|
+
Compile driver modules to JavaScript and export either an `AgentDriver`, a
|
|
64
|
+
`driver` value, or a zero-argument factory:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
AMALGM_AGENT_DRIVERS=./dist/codex-driver.js amalgm-agents-rest
|
|
68
|
+
amalgm-agents --drivers ./dist/codex-driver.js talk reviewer "Review this"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Multiple modules are comma-separated. Secret values belong in the host's
|
|
72
|
+
credential resolver, not in agent definitions or driver module arguments.
|
|
@@ -1,29 +1,74 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Amalgm Engine integration
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
supplies
|
|
3
|
+
Engine remains the composition root. This package becomes the canonical agent
|
|
4
|
+
registry and session ledger; Engine supplies adapters for everything outside
|
|
5
|
+
that domain.
|
|
5
6
|
|
|
6
|
-
##
|
|
7
|
+
## Existing ownership to replace
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
| Current Engine area | Destination |
|
|
10
|
+
|---|---|
|
|
11
|
+
| `amalgm-mcp/agents/store.js` agent rows | `AgentStore` through `Agents` |
|
|
12
|
+
| `amalgm-mcp/agent-config/*` normalized config | immutable agent definitions |
|
|
13
|
+
| `amalgm-mcp/agents/talk.js` durable sessions and logs | Agents sessions, turns, events |
|
|
14
|
+
| `amalgm-mcp/agents/tools.js` | packaged MCP tools |
|
|
15
|
+
| `amalgm-mcp/agents/rest.js` and route wiring | packaged REST adapter |
|
|
16
|
+
| `chat-core` native runtime execution | Engine-supplied `AgentDriver` implementations |
|
|
17
|
+
| Toolbox lookup and MCP resolution | `@amalgm/tools` adapter inside drivers |
|
|
18
|
+
| credential adapter | `authRef` resolver inside drivers |
|
|
19
|
+
| Supabase Chat session creation | Chat/cloud adapter observing Agents events |
|
|
12
20
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
other's database.
|
|
21
|
+
Agent bundle-v2 graph and agent install laws live here. Engine supplies the
|
|
22
|
+
`AgentBundlePort` that exports and installs apps, automations, and tools through
|
|
23
|
+
their public SDKs; neither side imports another product's store.
|
|
17
24
|
|
|
18
|
-
|
|
19
|
-
through the credential boundary. The resulting concrete values are frozen by
|
|
20
|
-
Chat before it accepts a turn.
|
|
25
|
+
## Required driver adapter
|
|
21
26
|
|
|
22
|
-
|
|
27
|
+
Engine should implement one driver per native harness identity (`codex`,
|
|
28
|
+
`claude_code`, `opencode`, `pi`, and others). A driver translates the immutable
|
|
29
|
+
revision into chat-core's runtime envelope, resolves `authRef`, projects the
|
|
30
|
+
Toolbox loadout, forwards normalized streaming events, and returns the native
|
|
31
|
+
session id for continuation.
|
|
23
32
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
33
|
+
Drivers must not write Agents SQLite or invent another conversation log.
|
|
34
|
+
|
|
35
|
+
## Chat boundary
|
|
36
|
+
|
|
37
|
+
Engine may associate an Agents session id with a Chat record. Chat owns title,
|
|
38
|
+
participants, layout, read state, and cloud presentation. Agents owns pinned
|
|
39
|
+
revision, accepted inputs, driver execution, and events. Synchronization is an
|
|
40
|
+
adapter subscribed to committed Agents events; neither database is imported by
|
|
41
|
+
the other product.
|
|
42
|
+
|
|
43
|
+
## One-time migration
|
|
44
|
+
|
|
45
|
+
1. Stop the legacy agent mutation and talk surfaces.
|
|
46
|
+
2. Read each legacy agent plus its `agent_config` as one complete definition.
|
|
47
|
+
3. Map `baseHarnessId` to `driver.id`, model fields to `model`, auth mode to an
|
|
48
|
+
`authRef`, and legacy loadout ids to `toolbox.toolIds`.
|
|
49
|
+
4. Create missing agents and update existing agents through `Agents`.
|
|
50
|
+
5. Import local conversation JSONL as archived sessions only when its agent and
|
|
51
|
+
chronological message identity are unambiguous; otherwise retain it as a
|
|
52
|
+
legacy read-only export.
|
|
53
|
+
6. Start packaged REST and MCP adapters behind Engine's existing authenticated
|
|
54
|
+
routes.
|
|
55
|
+
7. Enable native drivers and verify continuation against real harness sessions.
|
|
56
|
+
8. Delete the legacy registry, config, talk, REST, and MCP implementations only
|
|
57
|
+
after parity and rollback checks pass.
|
|
58
|
+
|
|
59
|
+
Migration must be idempotent. Record the source identity and migration version
|
|
60
|
+
outside agent metadata or in a namespaced metadata field; never manufacture a
|
|
61
|
+
new revision on equal reruns.
|
|
62
|
+
|
|
63
|
+
## Integration tests
|
|
64
|
+
|
|
65
|
+
Before switchover, run:
|
|
66
|
+
|
|
67
|
+
- legacy agent create/update/delete through the UI against `Agents`;
|
|
68
|
+
- a session created on revision 1, followed by an agent edit and continuation;
|
|
69
|
+
- native resume after Engine restart;
|
|
70
|
+
- Toolbox loadout enforcement through `@amalgm/tools`;
|
|
71
|
+
- provider authentication failure without credential persistence in Agents;
|
|
72
|
+
- agent-to-agent background calls and cancellation;
|
|
73
|
+
- Chat projection without Chat becoming the session source of truth; and
|
|
74
|
+
- one-time migration twice with byte-for-byte equal resulting definitions.
|
package/docs/MCP.md
CHANGED
|
@@ -3,6 +3,22 @@
|
|
|
3
3
|
`amalgm-agents-mcp` is the standalone stdio server. `createMcpServer` from
|
|
4
4
|
`@amalgm/agents/mcp` embeds the same server.
|
|
5
5
|
|
|
6
|
-
It exposes
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
It exposes seven tools:
|
|
7
|
+
|
|
8
|
+
| Tool | Purpose |
|
|
9
|
+
|---|---|
|
|
10
|
+
| `agents_list` | List persistent agents |
|
|
11
|
+
| `agents_get` | Inspect one agent |
|
|
12
|
+
| `agents_create` | Create an agent |
|
|
13
|
+
| `agents_update` | Edit an agent |
|
|
14
|
+
| `agents_delete` | Delete an agent while retaining session history |
|
|
15
|
+
| `agents_get_conversation` | Inspect a durable agent session |
|
|
16
|
+
| `talk_to_agent` | Start or continue an agent session |
|
|
17
|
+
|
|
18
|
+
`talk_to_agent` accepts the legacy `agent`, `conversation_id`, `description`,
|
|
19
|
+
and `prompt` fields. `agent_id`, `session_id`, and structured `message` are
|
|
20
|
+
also accepted. It returns `conversation_id` as the durable Agents session ID,
|
|
21
|
+
not a Chat ID. Use `run_in_background` for long work.
|
|
22
|
+
|
|
23
|
+
All handlers call the injected `Agents` service. MCP contains no second
|
|
24
|
+
registry, transcript, execution engine, or routing subsystem.
|
package/docs/REST.md
CHANGED
|
@@ -1,20 +1,103 @@
|
|
|
1
1
|
# REST API
|
|
2
2
|
|
|
3
|
-
Create an embeddable server with `createRestServer` from
|
|
4
|
-
or run `amalgm-agents-rest`.
|
|
3
|
+
Create an embeddable server with `createRestServer` from
|
|
4
|
+
`@amalgm/agents/http`, or run `amalgm-agents-rest`.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
The CLI default is `127.0.0.1:4317`. If a token is configured, all `/v1`
|
|
7
|
+
requests require the token via `Authorization: Bearer <token>` (scheme
|
|
8
|
+
case-insensitive) or the `x-amalgm-runtime-token` header. A missing or wrong
|
|
9
|
+
token receives the kernel's canonical 401 from `@amalgm/core/transport`,
|
|
10
|
+
compared in constant time. `/healthz` is a minimal unauthenticated liveness
|
|
11
|
+
response. JSON bodies default to a 512 KB limit.
|
|
12
|
+
|
|
13
|
+
## Agent configuration
|
|
14
|
+
|
|
15
|
+
| Method | Path | Result |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| `GET` | `/agent-config` | List normalized configs from live agent revisions |
|
|
18
|
+
| `POST` | `/agent-config/get` | Read `{ agent_id }` |
|
|
19
|
+
| `POST` | `/agent-config/update` | Atomically apply `{ agent_id, config }` |
|
|
20
|
+
| `POST` | `/agent-config/import-native` | Import safe native fields for `{ agent_id, replace? }` |
|
|
21
|
+
|
|
22
|
+
Set `nativeHomeDir` when embedding the server or `--native-home`/
|
|
23
|
+
`AMALGM_NATIVE_HOME` with the REST binary. Native import intentionally ignores
|
|
24
|
+
auth files, secrets, and MCP server configuration.
|
|
25
|
+
|
|
26
|
+
## Agent bundles
|
|
27
|
+
|
|
28
|
+
| Method | Path | Result |
|
|
29
|
+
|---|---|---|
|
|
30
|
+
| `GET` | `/agent-bundles` | Read bundle-v2 capability and available agent heads |
|
|
31
|
+
| `POST` | `/agent-bundles/preview` | Export requested agent/app/automation/tool heads |
|
|
32
|
+
| `POST` | `/agent-bundles/install` | Validate and install `{ bundle, auth_ref? }` |
|
|
33
|
+
|
|
34
|
+
Embedding hosts inject `bundlePort` for resources owned by Apps, Automations,
|
|
35
|
+
and Toolbox. Agent-only bundles need no port. Bundles with external resources
|
|
36
|
+
fail explicitly when the owner port is absent.
|
|
37
|
+
|
|
38
|
+
## Agents
|
|
9
39
|
|
|
10
40
|
| Method | Path | Result |
|
|
11
41
|
|---|---|---|
|
|
12
|
-
| `GET` | `/v1/agents` | List
|
|
13
|
-
| `POST` | `/v1/agents` | Create from
|
|
14
|
-
| `GET` | `/v1/agents/:id` | Read
|
|
15
|
-
| `PATCH` | `/v1/agents/:id` |
|
|
16
|
-
| `DELETE` | `/v1/agents/:id` | Tombstone
|
|
17
|
-
|
|
18
|
-
Use `?include_deleted=true` on list or get to include tombstones.
|
|
19
|
-
|
|
20
|
-
|
|
42
|
+
| `GET` | `/v1/agents` | List live agents |
|
|
43
|
+
| `POST` | `/v1/agents` | Create from complete body |
|
|
44
|
+
| `GET` | `/v1/agents/:id` | Read current definition |
|
|
45
|
+
| `PATCH` | `/v1/agents/:id` | Merge a definition patch |
|
|
46
|
+
| `DELETE` | `/v1/agents/:id` | Tombstone agent |
|
|
47
|
+
|
|
48
|
+
Use `?include_deleted=true` on list or get to include tombstones.
|
|
49
|
+
|
|
50
|
+
## Sessions
|
|
51
|
+
|
|
52
|
+
| Method | Path | Result |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| `GET` | `/v1/sessions` | List sessions |
|
|
55
|
+
| `POST` | `/v1/sessions` | Start `{ agentId, revisionId?, sessionId?, metadata? }` |
|
|
56
|
+
| `GET` | `/v1/sessions/:id` | Read session |
|
|
57
|
+
| `DELETE` | `/v1/sessions/:id` | Archive inactive session |
|
|
58
|
+
| `GET` | `/v1/sessions/:id/turns` | List turns |
|
|
59
|
+
| `GET` | `/v1/sessions/:id/events` | List ordered events |
|
|
60
|
+
| `POST` | `/v1/sessions/:id/messages` | Send a turn |
|
|
61
|
+
| `POST` | `/v1/sessions/:id/cancel` | Cancel active turn |
|
|
62
|
+
|
|
63
|
+
List filters are `agent_id` and `include_archived=true`. Event pagination uses
|
|
64
|
+
`after` and `limit` (maximum 1000).
|
|
65
|
+
|
|
66
|
+
Send a message:
|
|
67
|
+
|
|
68
|
+
```json
|
|
69
|
+
{
|
|
70
|
+
"message": "Review the current diff.",
|
|
71
|
+
"idempotencyKey": "review-001",
|
|
72
|
+
"wait": true
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`message` may also be a structured `AgentMessage`. `wait: false` returns `202`
|
|
77
|
+
after durable acceptance; otherwise the response waits for a terminal turn.
|
|
78
|
+
|
|
79
|
+
## Server-sent events
|
|
80
|
+
|
|
81
|
+
Connect to:
|
|
82
|
+
|
|
83
|
+
```text
|
|
84
|
+
GET /v1/sessions/:id/events/stream?after=<last-sequence>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
The stream sends committed backlog first and then live events. SSE `id` equals
|
|
88
|
+
the session sequence. Reconnect with the last seen id as `after`. Heartbeat
|
|
89
|
+
comments are sent every 15 seconds.
|
|
90
|
+
|
|
91
|
+
## Errors
|
|
92
|
+
|
|
93
|
+
Errors use the HTTP status associated with `AgentError`:
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"error": {
|
|
98
|
+
"code": "conflict",
|
|
99
|
+
"message": "Session already has an active turn.",
|
|
100
|
+
"details": {}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
package/docs/SDK.md
CHANGED
|
@@ -1,23 +1,72 @@
|
|
|
1
1
|
# SDK reference
|
|
2
2
|
|
|
3
|
-
`Agents` is the public behavior boundary
|
|
4
|
-
|
|
3
|
+
The `Agents` class is the sole public behavior boundary. All mutations are
|
|
4
|
+
durable before a method returns.
|
|
5
|
+
|
|
6
|
+
## Construction
|
|
5
7
|
|
|
6
8
|
```ts
|
|
7
|
-
const agents = new Agents({
|
|
9
|
+
const agents = new Agents({
|
|
10
|
+
stateDir: './state',
|
|
11
|
+
drivers: [codexDriver],
|
|
12
|
+
maxInputBytes: 256_000,
|
|
13
|
+
maxEventBytes: 256_000,
|
|
14
|
+
turnTimeoutMs: 600_000,
|
|
15
|
+
});
|
|
8
16
|
```
|
|
9
17
|
|
|
10
|
-
`databasePath` overrides the database location directly.
|
|
11
|
-
the
|
|
18
|
+
`databasePath` overrides the database location directly. `turnTimeoutMs: 0`
|
|
19
|
+
disables the service timeout. Call `close()` to abort owned executions, wait
|
|
20
|
+
for them to settle, and close SQLite.
|
|
21
|
+
|
|
22
|
+
## Agent methods
|
|
12
23
|
|
|
13
24
|
| Method | Behavior |
|
|
14
25
|
|---|---|
|
|
15
|
-
| `createAgent(definition)` | Create
|
|
16
|
-
| `updateAgent(id, patch)` |
|
|
17
|
-
| `deleteAgent(id)` | Tombstone the identity while retaining
|
|
26
|
+
| `createAgent(definition)` | Create identity and revision 1; conflicts on any reused id |
|
|
27
|
+
| `updateAgent(id, patch)` | Merge a patch and apply the resulting definition |
|
|
28
|
+
| `deleteAgent(id)` | Tombstone the identity while retaining history |
|
|
18
29
|
| `getAgent(id, includeDeleted?)` | Read the current definition |
|
|
19
|
-
| `listAgents(includeDeleted?)` | List
|
|
20
|
-
|
|
30
|
+
| `listAgents(includeDeleted?)` | List live agents by default |
|
|
31
|
+
|
|
32
|
+
## Session methods
|
|
33
|
+
|
|
34
|
+
| Method | Behavior |
|
|
35
|
+
|---|---|
|
|
36
|
+
| `startSession(input)` | Pin a new session to the current or named revision |
|
|
37
|
+
| `talk(agentId, input)` | Start or continue a session, then enqueue a turn |
|
|
38
|
+
| `enqueue(sessionId, input)` | Return immediately with the turn and completion promise |
|
|
39
|
+
| `send(sessionId, input)` | Wait for the turn's terminal state |
|
|
40
|
+
| `cancelSession(id)` | Persist cancellation intent and signal its active driver |
|
|
41
|
+
| `archiveSession(id)` | Archive an inactive session |
|
|
42
|
+
| `listSessions(agentId?, includeArchived?)` | Discover durable sessions |
|
|
43
|
+
| `listTurns(sessionId)` | Read accepted inputs and outcomes |
|
|
44
|
+
| `listEvents(sessionId, after?, limit?)` | Read ordered events |
|
|
45
|
+
|
|
46
|
+
`enqueue` returns `{ turn, completion, duplicate }`. If an idempotency key was
|
|
47
|
+
already accepted, `duplicate` is true and the original turn is returned.
|
|
48
|
+
|
|
49
|
+
## Event subscription
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
const unsubscribe = agents.subscribe(session.id, (event) => {
|
|
53
|
+
console.log(event.sequence, event.type, event.data);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
await agents.send(session.id, { message: 'Hello' });
|
|
57
|
+
unsubscribe();
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Listeners receive events only after commit. To build a reconnectable consumer,
|
|
61
|
+
read `listEvents(after)` before subscribing and de-duplicate by sequence, as
|
|
62
|
+
the packaged SSE adapter does.
|
|
63
|
+
|
|
64
|
+
## Errors
|
|
65
|
+
|
|
66
|
+
Expected failures use `AgentError` with a stable code:
|
|
67
|
+
|
|
68
|
+
`invalid_input`, `not_found`, `conflict`, `deleted`, `driver_unavailable`,
|
|
69
|
+
`too_large`, or `cancelled`.
|
|
21
70
|
|
|
22
|
-
|
|
23
|
-
|
|
71
|
+
Driver failures become durable failed turns rather than escaping as transient
|
|
72
|
+
transport errors. Inspect `turn.error` and the session event ledger.
|
package/docs/SECURITY.md
CHANGED
|
@@ -1,9 +1,38 @@
|
|
|
1
1
|
# Security model
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
and authorizes them while preparing a Chat execution.
|
|
3
|
+
Agents stores executable configuration and conversation history, so its state
|
|
4
|
+
directory should be treated as user-private data.
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
## Secrets
|
|
7
|
+
|
|
8
|
+
Agent definitions contain `authRef`, not credentials. Drivers resolve that
|
|
9
|
+
reference at execution time through the host's credential boundary. Do not put
|
|
10
|
+
tokens, cookies, private keys, or passwords in `driver.config`, `metadata`,
|
|
11
|
+
messages, or events.
|
|
12
|
+
|
|
13
|
+
## Capability references
|
|
14
|
+
|
|
15
|
+
Toolbox ids and subagent ids are requests, not authority. The composing host
|
|
16
|
+
must resolve them against the caller's allowed Toolbox view and agent policy.
|
|
17
|
+
Agents never infers permission merely because an id appears in a definition.
|
|
18
|
+
|
|
19
|
+
## REST exposure
|
|
20
|
+
|
|
21
|
+
The REST CLI binds `127.0.0.1` by default. Configure a bearer token before
|
|
22
|
+
binding to a LAN, container bridge, tunnel, or public interface. The packaged
|
|
23
|
+
server intentionally does not implement browser sessions, CORS, TLS, user
|
|
24
|
+
accounts, or cloud authorization; Engine supplies those outer boundaries.
|
|
25
|
+
|
|
26
|
+
## Driver trust
|
|
27
|
+
|
|
28
|
+
Drivers execute inside the hosting process and are trusted code. A driver can
|
|
29
|
+
read its process environment and access the filesystem with that process's
|
|
30
|
+
permissions. Load only reviewed modules. Native process drivers should avoid a
|
|
31
|
+
shell, pass explicit arguments, bound output, and kill their child on abort.
|
|
32
|
+
|
|
33
|
+
## Stored data
|
|
34
|
+
|
|
35
|
+
SQLite files are created beneath a mode-`0700` state directory. Application
|
|
36
|
+
packaging and backups must preserve appropriate filesystem permissions.
|
|
37
|
+
Messages and driver events may contain sensitive user content; retention and
|
|
38
|
+
export policies belong to the embedding product.
|
package/examples/basic.ts
CHANGED
|
@@ -1,17 +1,31 @@
|
|
|
1
|
-
import { Agents } from '@amalgm/agents';
|
|
1
|
+
import { Agents, defineDriver, messageText } from '@amalgm/agents';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const echo = defineDriver({
|
|
4
|
+
id: 'echo',
|
|
5
|
+
async run(request) {
|
|
6
|
+
return {
|
|
7
|
+
driverSessionId: request.driverSessionId || `echo-${request.session.id}`,
|
|
8
|
+
message: {
|
|
9
|
+
role: 'assistant',
|
|
10
|
+
parts: [{ type: 'text', text: `Echo: ${messageText(request.input)}` }],
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
},
|
|
14
|
+
});
|
|
4
15
|
|
|
5
|
-
|
|
16
|
+
async function main(): Promise<void> {
|
|
17
|
+
const agents = new Agents({ stateDir: './example-state', drivers: [echo] });
|
|
6
18
|
agents.createAgent({
|
|
7
19
|
id: 'reviewer',
|
|
8
20
|
name: 'Reviewer',
|
|
9
|
-
driver: '
|
|
21
|
+
driver: 'echo',
|
|
10
22
|
instructions: 'Review carefully.',
|
|
11
23
|
});
|
|
12
24
|
|
|
13
|
-
const
|
|
14
|
-
console.log(
|
|
15
|
-
|
|
16
|
-
agents.close();
|
|
25
|
+
const call = agents.talk('reviewer', { message: 'Check this design.' });
|
|
26
|
+
console.log(await call.completion);
|
|
27
|
+
console.log(agents.listEvents(call.session.id));
|
|
28
|
+
await agents.close();
|
|
17
29
|
}
|
|
30
|
+
|
|
31
|
+
void main();
|