Skip to content

Commit 16d0d77

Browse files
feat(tools): carry the memory tools through a sidecar bundle on run-scoped routes (#43)
The legacy defineTool factories were thin hub clients configured with a base URL, tenant id and bearer in agent env. They are replaced by one convention-compliant bundle at @corbits/memory/sidecar-bundle that resolves the "hub" credential handle from the host's runtime capabilities and calls a new parallel mount, mountWorkflowMemory, scoped to the verified run's tenant and principal. The human-facing tenant routes keep their session auth.
1 parent e74da20 commit 16d0d77

23 files changed

Lines changed: 1073 additions & 1231 deletions

‎AGENTS.md‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,11 @@ CI runs `typecheck` + `test` — both must pass before any push.
2424
- `src/mount-config.ts` / `src/config.ts` — mount config + engine config
2525
- `src/routes/` — Hono routes (`add`, `search`, `list`, `feed`, retention
2626
`forget`/`purge`/`retention-class`)
27-
- `src/tools/` — Interchange `defineTool` factories (`@corbits/memory/tools`);
28-
HTTP clients for mounted routes (env credentials; no in-process plane)
27+
- `src/workflow-mount.ts` — run-scoped routes for deployed agents (agent-token
28+
bearer + run address; no session auth)
29+
- `src/sidecar-bundle.ts` + `src/tools.ts` — the agent tool bundle
30+
(`@corbits/memory/sidecar-bundle`) and its tool descriptors
31+
- `src/http-client.ts` — host-side HTTP client for the tenant routes
2932
- `src/services/` — capture / search / transform internals (not public verbs)
3033
- `src/ports/` — `DocumentStore` / `SourceProvider` + fakes
3134
- `src/core/` — embed/rerank clients, merge, arktype schemas

‎README.md‎

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ Memory for [Interchange](https://github.com/corbitsdev) hubs: **add**, **search*
55

66
Mount it on the hub. Routes land under `/api/tenants/:tenantId/memory/*`, so
77
the hub’s existing `createResolveTenant` middleware supplies principal + tenant
8-
— same as workflows, assets, and agents. Workflow agents install the package’s
9-
`defineTool` factories; ingestion modules call the same routes or the in-process
10-
plane. That’s the product.
8+
— same as workflows, assets, and agents. Deployed agents carry the sidecar
9+
bundle and call the run-scoped routes under `/api/workflow-memory/*`;
10+
ingestion modules call the tenant routes or the in-process plane. That’s the
11+
product.
1112

1213
Requires Bun 1.2+.
1314

@@ -57,46 +58,47 @@ POST /api/tenants/:tenantId/memory/search { "query", "limit"?, "kinds"?, "enti
5758
GET /api/tenants/:tenantId/memory/list ?limit=
5859
```
5960

60-
## Workflow agent tools
61+
## Agent tools (sidecar bundle)
6162

62-
This package exports Interchange `defineTool` factories at
63-
`@corbits/memory/tools` (also `package.json` → `interchange.tools`). Each tool
64-
is a thin HTTP client: install credentials in agent env, call the mounted hub
65-
routes. No plane inject, no model-supplied identity.
63+
A deployed agent carries the memory tools through one factory at
64+
`@corbits/memory/sidecar-bundle`. It holds no client code, no base URL and no
65+
token: it resolves the `hub` credential handle from the host-assembled runtime
66+
capabilities and calls the run-scoped routes through that mediated fetch,
67+
naming its run with the `x-workflow-run-address` header.
6668

67-
| Factory id | Tool name | HTTP |
68-
| --- | --- | --- |
69-
| `@corbits/memory/add` | `memory_add` | `POST …/memory/add` |
70-
| `@corbits/memory/search` | `memory_search` | `POST …/memory/search` |
71-
| `@corbits/memory/list` | `memory_list` | `GET …/memory/list` |
72-
73-
**Env keys** (declared on each factory’s `requires`):
74-
75-
| Key | Meaning |
69+
| Tool | Route |
7670
| --- | --- |
77-
| `memoryBaseUrl` | Hub **origin** only, e.g. `https://hub.example` (no `/api/...` path) |
78-
| `memoryTenantId` | Tenant path segment (must match the principal’s tenant on the hub) |
79-
| `memoryAuthToken` | Bearer token the hub accepts for that agent principal |
80-
81-
**Host checklist**
71+
| `memory_add` | `POST /api/workflow-memory/add` |
72+
| `memory_search` | `POST /api/workflow-memory/search` |
73+
| `memory_list` | `GET /api/workflow-memory/list` |
74+
| `memory_feed` | `GET /api/workflow-memory/feed` |
8275

83-
1. Mount routes: `createMemory({ app, grantStore, … })` under the hub tenant tree.
84-
2. Grant the agent principal `memory:add` and/or `memory:search` (`list` uses `search`).
85-
3. For peer/space share visibility, also grant `search` on the relevant document tags (see `docs/AUTHZ-DOCUMENT-ACCESS.md`).
86-
4. Install factories on the workflow and set the three env keys above.
87-
5. Auth is **Bearer only** on the tool client — session cookies are not sent.
88-
6. Tool results are **JSON strings** (`stringTool`); pass `AbortSignal` if you need hang protection (no default client timeout).
76+
Those routes are a **second, parallel mount** — the tenant routes above keep
77+
their session auth untouched:
8978

9079
```ts
91-
import { memoryAdd, memorySearch, memoryList } from "@corbits/memory/tools";
80+
import { mountWorkflowMemory } from "@corbits/memory";
9281

93-
// On a workflow / agent definition — install like any open tool package:
94-
// tools: [memoryAdd, memorySearch, memoryList]
95-
// and supply memoryBaseUrl / memoryTenantId / memoryAuthToken in agent env.
82+
mountWorkflowMemory(workflowMemoryApi, {
83+
memory,
84+
agentToken: { verify, resolveRun }, // host's own token + run lookup
85+
});
86+
app.route("/api/workflow-memory", workflowMemoryApi);
9687
```
9788

98-
OpenAPI→MCP remains available as an alternative host bridge; the shipped
99-
`defineTool`s are the primary install path for workflow agents.
89+
`verify` returns `{ tenantId, definitionId }` for a recognized bearer (or
90+
`undefined`), `resolveRun` maps the run address to `{ tenantId, principalId,
91+
runId }`. A token whose tenant is not the run's tenant is refused with the same
92+
401 as an unknown bearer. Every call is scoped to that run's tenant and
93+
principal; the body never carries identity.
94+
95+
**Host checklist**
96+
97+
1. Mount the tenant routes: `createMemory({ app, grantStore, … })`.
98+
2. Mount `mountWorkflowMemory` and bind the agent's hub credential to the
99+
`hub` handle on its definition.
100+
3. For peer/space share visibility, grant `search` on the relevant document
101+
tags (see `docs/AUTHZ-DOCUMENT-ACCESS.md`).
100102

101103
## Ingestion (in-process)
102104

0 commit comments

Comments
 (0)