@synapsor/runner 0.1.0-alpha.7 → 0.1.0-alpha.9
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 +32 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/runner.mjs +29 -8
- package/docs/getting-started-own-database.md +5 -1
- package/docs/http-mcp.md +10 -2
- package/docs/local-mode.md +5 -1
- package/docs/mcp-client-setup.md +5 -0
- package/docs/security-boundary.md +7 -0
- package/docs/writeback-executors.md +32 -0
- package/examples/openai-agents-http/README.md +5 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,6 +7,25 @@ Runner lets an MCP agent inspect scoped data and request database-backed
|
|
|
7
7
|
business actions without receiving raw SQL, write credentials, approval tools,
|
|
8
8
|
or commit tools.
|
|
9
9
|
|
|
10
|
+
## Alpha Operational Notes
|
|
11
|
+
|
|
12
|
+
These are current alpha requirements, not hidden behavior:
|
|
13
|
+
|
|
14
|
+
- Writeback with `--config ./synapsor.runner.json` reads the trusted writer
|
|
15
|
+
connection from the source `write_url_env`, for example
|
|
16
|
+
`SYNAPSOR_DATABASE_WRITE_URL`. `SYNAPSOR_DATABASE_URL` is only the legacy
|
|
17
|
+
fallback when you run direct worker/apply flows without a local config.
|
|
18
|
+
- `synapsor-runner mcp serve-http` is a small authenticated JSON-RPC endpoint
|
|
19
|
+
for `tools/list`, `tools/call`, and `resources/read`. It is not full MCP
|
|
20
|
+
Streamable HTTP and does not implement the `initialize`/SSE handshake. Use
|
|
21
|
+
stdio MCP for standard local MCP clients, or wrap the HTTP endpoint like the
|
|
22
|
+
OpenAI HTTP example.
|
|
23
|
+
- Direct SQL writeback creates or writes `synapsor_writeback_receipts` for
|
|
24
|
+
idempotency and replay. The trusted writer needs permission for that table,
|
|
25
|
+
or an administrator must pre-create it and grant access. Use an app-owned
|
|
26
|
+
`http_handler` or `command_handler` if Runner should not create receipt
|
|
27
|
+
tables in your application schema.
|
|
28
|
+
|
|
10
29
|
```text
|
|
11
30
|
AI agent or MCP client
|
|
12
31
|
(Claude, Cursor, OpenAI Agents SDK, LangGraph)
|
|
@@ -171,6 +190,12 @@ HTTP defaults to `127.0.0.1:8765`, requires bearer auth by default, and should
|
|
|
171
190
|
use private networking, TLS, and rate limits before being exposed beyond a
|
|
172
191
|
local machine.
|
|
173
192
|
|
|
193
|
+
HTTP alpha scope: `serve-http` is a JSON-RPC endpoint for `tools/list`,
|
|
194
|
+
`tools/call`, and `resources/read`. It is not full MCP Streamable HTTP and does
|
|
195
|
+
not implement `initialize`/SSE. If an SDK HTTP MCP client expects that
|
|
196
|
+
handshake, use stdio mode or wrap the HTTP endpoint like the OpenAI HTTP
|
|
197
|
+
example.
|
|
198
|
+
|
|
174
199
|
OpenAI Agents SDK examples:
|
|
175
200
|
|
|
176
201
|
```text
|
|
@@ -347,6 +372,13 @@ your application service already owns business writes, configure an
|
|
|
347
372
|
`http_handler` or `command_handler` executor. Approval still happens outside
|
|
348
373
|
MCP, and the handler returns an applied/conflict/failed receipt for replay.
|
|
349
374
|
|
|
375
|
+
For direct SQL writeback, set the writer env var named by the source
|
|
376
|
+
`write_url_env`, for example `SYNAPSOR_DATABASE_WRITE_URL`. Runner also creates
|
|
377
|
+
or writes `synapsor_writeback_receipts` for idempotency/replay, so the writer
|
|
378
|
+
needs permission for that receipt table or an administrator must pre-create and
|
|
379
|
+
grant it. Use app-owned handlers when you do not want Runner creating receipt
|
|
380
|
+
tables in your application schema.
|
|
381
|
+
|
|
350
382
|
## Command Name
|
|
351
383
|
|
|
352
384
|
This package installs `synapsor-runner` as the OSS runner binary. The `synapsor`
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { type WritebackJob } from "@synapsor-runner/protocol";
|
|
2
3
|
import { type SchemaInspection } from "@synapsor-runner/schema-inspector";
|
|
3
4
|
export declare function main(argv: string[]): Promise<number>;
|
|
4
5
|
type WizardAsk = (question: string, defaultValue?: string) => Promise<string>;
|
|
@@ -8,5 +9,6 @@ export declare function runInitWizard(args: string[], options?: {
|
|
|
8
9
|
inspection?: SchemaInspection;
|
|
9
10
|
stdout?: Pick<NodeJS.WriteStream, "write">;
|
|
10
11
|
}): Promise<number>;
|
|
12
|
+
export declare function resolveSqlWriteDatabaseUrl(job: WritebackJob, configPath: string, env: NodeJS.ProcessEnv): Promise<string>;
|
|
11
13
|
export {};
|
|
12
14
|
//# sourceMappingURL=cli.d.ts.map
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AA8BA,OAAO,EAA6G,KAAK,YAAY,EAAwB,MAAM,2BAA2B,CAAC;AAC/L,OAAO,EAOL,KAAK,gBAAgB,EAEtB,MAAM,mCAAmC,CAAC;AA4H3C,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA8C1D;AA0DD,KAAK,SAAS,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAE9E,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE;IACP,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;CACvC,GACL,OAAO,CAAC,MAAM,CAAC,CAiLjB;AAsyCD,wBAAsB,0BAA0B,CAAC,GAAG,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAM/H"}
|
package/dist/runner.mjs
CHANGED
|
@@ -2685,7 +2685,7 @@ function createMcpRuntime(config, options = {}) {
|
|
|
2685
2685
|
}
|
|
2686
2686
|
function createSynapsorMcpServer(runtime) {
|
|
2687
2687
|
const server = new McpServer(
|
|
2688
|
-
{ name: "synapsor-runner", version: "0.1.0-alpha.
|
|
2688
|
+
{ name: "synapsor-runner", version: "0.1.0-alpha.9" },
|
|
2689
2689
|
{ capabilities: { tools: {}, resources: {} } }
|
|
2690
2690
|
);
|
|
2691
2691
|
if (runtime.config.mode === "cloud") {
|
|
@@ -3748,7 +3748,7 @@ function failed(job, config, code) {
|
|
|
3748
3748
|
}
|
|
3749
3749
|
var mysqlAdapter = {
|
|
3750
3750
|
async doctor(config) {
|
|
3751
|
-
if (!config.databaseUrl) return { ok: false, details: { error: "
|
|
3751
|
+
if (!config.databaseUrl) return { ok: false, details: { error: "database URL required; local config apply reads source.write_url_env, legacy workers use SYNAPSOR_DATABASE_URL" } };
|
|
3752
3752
|
const connection = await mysql2.createConnection({ uri: config.databaseUrl, dateStrings: true });
|
|
3753
3753
|
try {
|
|
3754
3754
|
const [rows] = await connection.query("SELECT VERSION() AS version");
|
|
@@ -3963,7 +3963,7 @@ function failed2(job, config, code) {
|
|
|
3963
3963
|
}
|
|
3964
3964
|
var postgresAdapter = {
|
|
3965
3965
|
async doctor(config) {
|
|
3966
|
-
if (!config.databaseUrl) return { ok: false, details: { error: "
|
|
3966
|
+
if (!config.databaseUrl) return { ok: false, details: { error: "database URL required; local config apply reads source.write_url_env, legacy workers use SYNAPSOR_DATABASE_URL" } };
|
|
3967
3967
|
const pool = new Pool2({ connectionString: config.databaseUrl });
|
|
3968
3968
|
const client = await pool.connect();
|
|
3969
3969
|
try {
|
|
@@ -7386,12 +7386,13 @@ async function apply(args) {
|
|
|
7386
7386
|
}
|
|
7387
7387
|
await verifyLocalWritebackAuthority(job, configPath, storePath);
|
|
7388
7388
|
}
|
|
7389
|
+
const databaseUrl = configPath ? await resolveSqlWriteDatabaseUrl(job, configPath, process2.env) : process2.env.SYNAPSOR_DATABASE_URL || "";
|
|
7389
7390
|
const config = {
|
|
7390
7391
|
controlPlaneUrl: process2.env.SYNAPSOR_CONTROL_PLANE_URL || "http://localhost:8000",
|
|
7391
7392
|
runnerToken: process2.env.SYNAPSOR_RUNNER_TOKEN || "local-dry-run-token",
|
|
7392
7393
|
runnerId: process2.env.SYNAPSOR_RUNNER_ID || "local-runner",
|
|
7393
7394
|
sourceId: process2.env.SYNAPSOR_SOURCE_ID || job.source_id,
|
|
7394
|
-
databaseUrl
|
|
7395
|
+
databaseUrl,
|
|
7395
7396
|
engine: job.engine,
|
|
7396
7397
|
pollIntervalMs: Number(process2.env.SYNAPSOR_POLL_INTERVAL_MS || "5000"),
|
|
7397
7398
|
logLevel: process2.env.SYNAPSOR_LOG_LEVEL || "info",
|
|
@@ -7468,12 +7469,13 @@ async function applyProposal(args, proposalId) {
|
|
|
7468
7469
|
async function applySqlJob(job, configPath, storePath, dryRun, env = process2.env) {
|
|
7469
7470
|
const parsedJob = parseWritebackJob(job);
|
|
7470
7471
|
await verifyLocalWritebackAuthority(parsedJob, configPath, storePath);
|
|
7472
|
+
const databaseUrl = await resolveSqlWriteDatabaseUrl(parsedJob, configPath, env);
|
|
7471
7473
|
const config = {
|
|
7472
7474
|
controlPlaneUrl: env.SYNAPSOR_CONTROL_PLANE_URL || "http://localhost:8000",
|
|
7473
7475
|
runnerToken: env.SYNAPSOR_RUNNER_TOKEN || "local-dry-run-token",
|
|
7474
7476
|
runnerId: env.SYNAPSOR_RUNNER_ID || "local-runner",
|
|
7475
7477
|
sourceId: env.SYNAPSOR_SOURCE_ID || parsedJob.source_id,
|
|
7476
|
-
databaseUrl
|
|
7478
|
+
databaseUrl,
|
|
7477
7479
|
engine: parsedJob.engine,
|
|
7478
7480
|
pollIntervalMs: Number(env.SYNAPSOR_POLL_INTERVAL_MS || "5000"),
|
|
7479
7481
|
logLevel: env.SYNAPSOR_LOG_LEVEL || "info",
|
|
@@ -7491,6 +7493,13 @@ async function applySqlJob(job, configPath, storePath, dryRun, env = process2.en
|
|
|
7491
7493
|
}
|
|
7492
7494
|
return result;
|
|
7493
7495
|
}
|
|
7496
|
+
async function resolveSqlWriteDatabaseUrl(job, configPath, env) {
|
|
7497
|
+
const config = JSON.parse(await fs3.readFile(configPath, "utf8"));
|
|
7498
|
+
const source = config.sources?.[job.source_id];
|
|
7499
|
+
const writeUrlEnv = source?.write_url_env;
|
|
7500
|
+
if (writeUrlEnv && env[writeUrlEnv]) return env[writeUrlEnv] ?? "";
|
|
7501
|
+
return env.SYNAPSOR_DATABASE_URL || "";
|
|
7502
|
+
}
|
|
7494
7503
|
function sourceNeedsSqlWriteback(config, sourceName) {
|
|
7495
7504
|
return (config.capabilities ?? []).some((capability) => {
|
|
7496
7505
|
if (capability.kind !== "proposal" || capability.source !== sourceName) return false;
|
|
@@ -7977,7 +7986,7 @@ async function cloudConnect(args) {
|
|
|
7977
7986
|
return 1;
|
|
7978
7987
|
}
|
|
7979
7988
|
const runnerId = String(parsed.cloud.runner_id || process2.env.SYNAPSOR_RUNNER_ID || "synapsor_runner_local").trim();
|
|
7980
|
-
const runnerVersion = String(parsed.cloud.runner_version || process2.env.npm_package_version || "0.1.0-alpha.
|
|
7989
|
+
const runnerVersion = String(parsed.cloud.runner_version || process2.env.npm_package_version || "0.1.0-alpha.9").trim();
|
|
7981
7990
|
const engines = normalizeEngines(parsed.cloud.engines);
|
|
7982
7991
|
const capabilities = normalizeCapabilities(parsed.cloud.capabilities);
|
|
7983
7992
|
const client = new ControlPlaneClient({
|
|
@@ -11435,7 +11444,7 @@ function starterCloudConfig() {
|
|
|
11435
11444
|
base_url_env: "SYNAPSOR_CLOUD_BASE_URL",
|
|
11436
11445
|
runner_token_env: "SYNAPSOR_RUNNER_TOKEN",
|
|
11437
11446
|
runner_id: "synapsor_runner_local",
|
|
11438
|
-
runner_version: "0.1.0-alpha.
|
|
11447
|
+
runner_version: "0.1.0-alpha.9",
|
|
11439
11448
|
project_id: "token_scope",
|
|
11440
11449
|
adapter_id: "mcp.your_adapter",
|
|
11441
11450
|
source_id: "src_replace_me",
|
|
@@ -11560,7 +11569,10 @@ Start the stdio MCP server for local MCP clients such as Claude Desktop, Cursor,
|
|
|
11560
11569
|
export SYNAPSOR_RUNNER_HTTP_TOKEN=...
|
|
11561
11570
|
${cmd} mcp serve-http --config ./synapsor.runner.json --store ./.synapsor/local.db [--host 127.0.0.1] [--port 8765] [--auth-token-env SYNAPSOR_RUNNER_HTTP_TOKEN]
|
|
11562
11571
|
|
|
11563
|
-
Start the HTTP MCP
|
|
11572
|
+
Start the HTTP JSON-RPC MCP endpoint for app/server deployments. Bearer auth is required by default.
|
|
11573
|
+
|
|
11574
|
+
Alpha scope: supports POST /mcp methods tools/list, tools/call, and resources/read.
|
|
11575
|
+
It does not implement full MCP Streamable HTTP initialize/SSE sessions.
|
|
11564
11576
|
|
|
11565
11577
|
Security:
|
|
11566
11578
|
- Defaults to 127.0.0.1:8765.
|
|
@@ -11643,6 +11655,14 @@ Inspect local query fingerprints, table names, row counts, and redacted-paramete
|
|
|
11643
11655
|
${cmd} apply --job job.json --config ./synapsor.runner.json --store ./.synapsor/local.db
|
|
11644
11656
|
|
|
11645
11657
|
Apply an approved proposal through guarded writeback. Requires a trusted write credential.
|
|
11658
|
+
|
|
11659
|
+
With --config, the writer connection comes from source.write_url_env, such as
|
|
11660
|
+
SYNAPSOR_DATABASE_WRITE_URL. SYNAPSOR_DATABASE_URL is only the legacy fallback
|
|
11661
|
+
for direct worker/apply flows without a local config.
|
|
11662
|
+
|
|
11663
|
+
Direct SQL writeback creates or writes synapsor_writeback_receipts for
|
|
11664
|
+
idempotency and replay, so the trusted writer needs permission for that table
|
|
11665
|
+
or an administrator must pre-create and grant it.
|
|
11646
11666
|
`,
|
|
11647
11667
|
replay: `Usage:
|
|
11648
11668
|
${cmd} replay list [--tenant acme] [--object invoice:INV-3001]
|
|
@@ -11714,5 +11734,6 @@ function formatCliErrorHint(message) {
|
|
|
11714
11734
|
}
|
|
11715
11735
|
export {
|
|
11716
11736
|
main,
|
|
11737
|
+
resolveSqlWriteDatabaseUrl,
|
|
11717
11738
|
runInitWizard
|
|
11718
11739
|
};
|
|
@@ -368,10 +368,14 @@ Apply through the trusted worker path with a separate writer credential:
|
|
|
368
368
|
```bash
|
|
369
369
|
export SYNAPSOR_DATABASE_WRITE_URL="<postgres-or-mysql-write-url>"
|
|
370
370
|
SYNAPSOR_ENGINE=postgres \
|
|
371
|
-
SYNAPSOR_DATABASE_URL="$SYNAPSOR_DATABASE_WRITE_URL" \
|
|
372
371
|
npx -y -p @synapsor/runner@alpha synapsor-runner apply --job job.json --config synapsor.runner.json --store ./.synapsor/local.db
|
|
373
372
|
```
|
|
374
373
|
|
|
374
|
+
For `apply --job ... --config ...`, Runner reads the write credential from the
|
|
375
|
+
source `write_url_env` in `synapsor.runner.json`, such as
|
|
376
|
+
`SYNAPSOR_DATABASE_WRITE_URL`. `SYNAPSOR_DATABASE_URL` is accepted only as a
|
|
377
|
+
legacy fallback for direct worker flows that do not pass a local config.
|
|
378
|
+
|
|
375
379
|
If your application/API should own the business write, use an `http_handler`
|
|
376
380
|
executor instead of direct SQL writeback. Handler URLs and bearer tokens come
|
|
377
381
|
from environment variables, and the handler receives a structured proposal/job
|
package/docs/http-mcp.md
CHANGED
|
@@ -6,6 +6,13 @@ needs to connect to a long-running Synapsor Runner service.
|
|
|
6
6
|
Use stdio MCP when a local MCP client such as Claude Desktop, Cursor, or a
|
|
7
7
|
local agent tool can launch Synapsor Runner directly.
|
|
8
8
|
|
|
9
|
+
Current alpha scope: `serve-http` exposes a small authenticated JSON-RPC
|
|
10
|
+
endpoint at `POST /mcp` for `tools/list`, `tools/call`, and `resources/read`.
|
|
11
|
+
It is not the full MCP Streamable HTTP transport and does not implement an
|
|
12
|
+
`initialize`/SSE session handshake. If your SDK expects full HTTP MCP
|
|
13
|
+
initialization, use stdio mode or wrap this endpoint with a thin tool/function
|
|
14
|
+
adapter like the OpenAI HTTP example.
|
|
15
|
+
|
|
9
16
|
## Start The HTTP Server
|
|
10
17
|
|
|
11
18
|
```bash
|
|
@@ -196,5 +203,6 @@ examples/openai-agents-stdio/
|
|
|
196
203
|
The stdio example uses the MCP client integration from the OpenAI Agents SDK
|
|
197
204
|
when available. The HTTP example uses a minimal JSON-RPC client wrapped as an
|
|
198
205
|
OpenAI function tool because native HTTP MCP client support can vary by SDK
|
|
199
|
-
version
|
|
200
|
-
|
|
206
|
+
version and Runner's HTTP alpha endpoint is intentionally limited to JSON-RPC
|
|
207
|
+
tool/resource calls. The boundary is the same: the agent calls a semantic
|
|
208
|
+
Synapsor tool, not raw SQL.
|
package/docs/local-mode.md
CHANGED
|
@@ -158,11 +158,15 @@ npx -y -p @synapsor/runner@alpha synapsor-runner proposals writeback-job wrp_123
|
|
|
158
158
|
The generated job uses the public `synapsor.writeback-job.v1` protocol and can be applied by the guarded worker:
|
|
159
159
|
|
|
160
160
|
```bash
|
|
161
|
+
export SYNAPSOR_DATABASE_WRITE_URL="postgresql://writer:<password>@localhost:5432/app"
|
|
161
162
|
SYNAPSOR_ENGINE=postgres \
|
|
162
|
-
SYNAPSOR_DATABASE_URL="postgresql://writer:<password>@localhost:5432/app" \
|
|
163
163
|
npx -y -p @synapsor/runner@alpha synapsor-runner apply --job job.json --config synapsor.runner.json --store ./.synapsor/local.db
|
|
164
164
|
```
|
|
165
165
|
|
|
166
|
+
When `--config` is passed, direct SQL writeback reads the writer connection from
|
|
167
|
+
the source `write_url_env` in that config. `SYNAPSOR_DATABASE_URL` is only a
|
|
168
|
+
legacy fallback for direct worker flows without a local runner config.
|
|
169
|
+
|
|
166
170
|
Passing `--store` records the terminal `synapsor.execution-receipt.v1` locally. Replay then links the proposal, approval, writeback job, applied/conflict/failed receipt, evidence, and query audit.
|
|
167
171
|
|
|
168
172
|
Reject:
|
package/docs/mcp-client-setup.md
CHANGED
|
@@ -38,6 +38,11 @@ Stdio keeps the MCP protocol on process stdin/stdout and is the simplest local
|
|
|
38
38
|
developer path. HTTP uses JSON-RPC over an authenticated `/mcp` endpoint and is
|
|
39
39
|
better for app/server deployments.
|
|
40
40
|
|
|
41
|
+
Important alpha limitation: HTTP mode is not full MCP Streamable HTTP. It does
|
|
42
|
+
not implement `initialize` or an SSE session handshake. Standard SDK HTTP MCP
|
|
43
|
+
clients that require initialization may fail. Use stdio for those clients, or
|
|
44
|
+
call Runner's HTTP JSON-RPC endpoint through a thin app/server wrapper.
|
|
45
|
+
|
|
41
46
|
HTTP requires bearer auth by default:
|
|
42
47
|
|
|
43
48
|
```bash
|
|
@@ -65,6 +65,13 @@ outside the model-facing MCP server and verifies:
|
|
|
65
65
|
|
|
66
66
|
If any authority check cannot be verified, the write fails closed.
|
|
67
67
|
|
|
68
|
+
For direct SQL writeback, the writer connection is the env var named by the
|
|
69
|
+
source `write_url_env` in `synapsor.runner.json`. Direct SQL writeback also
|
|
70
|
+
creates or writes `synapsor_writeback_receipts` for idempotency and replay, so
|
|
71
|
+
the writer needs permission for that receipt table or an administrator must
|
|
72
|
+
pre-create and grant it. If your database policy forbids Runner-managed receipt
|
|
73
|
+
tables, use an app-owned `http_handler` or `command_handler` executor instead.
|
|
74
|
+
|
|
68
75
|
When a capability uses an `http_handler` or `command_handler` executor, the
|
|
69
76
|
same approval boundary applies. The runner sends a structured proposal/job
|
|
70
77
|
payload to the configured handler after approval. Handler URLs, commands, bearer
|
|
@@ -24,6 +24,38 @@ It applies one guarded `UPDATE` through the database adapter:
|
|
|
24
24
|
Use this when the trusted runner is allowed to update the selected business row
|
|
25
25
|
directly.
|
|
26
26
|
|
|
27
|
+
The source config controls which writer env var is used:
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"sources": {
|
|
32
|
+
"local_postgres": {
|
|
33
|
+
"engine": "postgres",
|
|
34
|
+
"read_url_env": "SYNAPSOR_DATABASE_READ_URL",
|
|
35
|
+
"write_url_env": "SYNAPSOR_DATABASE_WRITE_URL"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
For `synapsor-runner apply --job ... --config ...`, set the env var named by
|
|
42
|
+
`write_url_env`. `SYNAPSOR_DATABASE_URL` is only a legacy fallback for direct
|
|
43
|
+
worker flows that do not pass a local config.
|
|
44
|
+
|
|
45
|
+
Direct SQL writeback also stores idempotency receipts in the source database.
|
|
46
|
+
By default it runs:
|
|
47
|
+
|
|
48
|
+
```sql
|
|
49
|
+
CREATE TABLE IF NOT EXISTS synapsor_writeback_receipts (...);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
That means the writer needs permission to create and write that receipt table in
|
|
53
|
+
the target schema/database, or the table must be pre-created by an administrator
|
|
54
|
+
and granted to the writer. If you do not want Runner to create a table in the
|
|
55
|
+
application schema, create a dedicated schema/database for receipts where your
|
|
56
|
+
database policy allows it, or use `http_handler`/`command_handler` so your
|
|
57
|
+
application owns receipt storage and business writes.
|
|
58
|
+
|
|
27
59
|
## `http_handler`
|
|
28
60
|
|
|
29
61
|
Use `http_handler` when your application/API should own business execution.
|
|
@@ -7,9 +7,11 @@ Use HTTP when your agent runs as an app/server and should connect to Runner
|
|
|
7
7
|
over a local/private network endpoint instead of launching a stdio child
|
|
8
8
|
process.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
HTTP
|
|
10
|
+
Runner's HTTP alpha endpoint is a small authenticated JSON-RPC surface for
|
|
11
|
+
`tools/list`, `tools/call`, and `resources/read`. It is not the full MCP
|
|
12
|
+
Streamable HTTP transport and does not implement `initialize`/SSE. This example
|
|
13
|
+
therefore uses the OpenAI Agents SDK for the agent and wraps Synapsor's HTTP
|
|
14
|
+
JSON-RPC endpoint as an OpenAI function tool.
|
|
13
15
|
|
|
14
16
|
The model still sees a semantic action. It does not receive raw SQL, database
|
|
15
17
|
URLs, write credentials, approval tools, or commit tools.
|