{"id":"ops/ag2-worker","relativePath":"ops/ag2-worker.md","title":"AG2 Worker and Bridge Runbook","markdown":"# AG2 Worker and Bridge Runbook\n\nThis runbook covers the local review-only AG2 worker and the disabled-by-default\nNext.js bridge that can delegate Mercator and Janus review execution.\n\nService path:\n\n- `services/ag2-worker/`\n\nBridge owner:\n\n- `src/services/ag2-bridge.ts`\n\nWhat it does:\n\n- Exposes `GET /health` for local worker readiness.\n- Exposes `POST /ag2/agents/run` for internal, server-side review execution.\n- Accepts only Mercator and Janus.\n- Preserves the existing `AgentTask` envelope and human approval gate.\n- Records trace metadata from `x-request-id`, `traceparent`, and the bridge\n  request body.\n- Falls back to local TypeScript review when disabled, missing URL, invalid\n  response, HTTP failure, or timeout occurs.\n\nWhat it must not do:\n\n- Publish, merge identities, clear rights, activate imports, or write\n  `equivalent` links.\n- Expose A2A, AG-UI, or LAN/public agent endpoints.\n- Accept agents other than Mercator and Janus without new tests and review.\n- Run with secrets passed through tool arguments or client-visible schemas.\n\n## Install Deps\n\n```bash\npnpm ag2:worker:deps\n```\n\n## Run Locally\n\n```bash\npnpm ag2:worker\n```\n\nDefault bind:\n\n- `http://127.0.0.1:7788`\n\n## Health Check\n\n```bash\ncurl http://127.0.0.1:7788/health\n```\n\nExpected shape:\n\n```json\n{\n  \"ok\": true,\n  \"service\": \"ag2-worker\",\n  \"eligibleAgents\": [\"mercator\", \"janus\"],\n  \"reviewOnly\": true\n}\n```\n\n## Enable Bridge Locally\n\nKeep the worker loopback-only, start the worker, then start the Next app with\nthe bridge enabled:\n\n```bash\npnpm ag2:worker\n```\n\nIn the app environment:\n\n```bash\nMETAMUSEUM_AG2_BRIDGE_ENABLED=1\nMETAMUSEUM_AG2_BRIDGE_URL=http://127.0.0.1:7788/ag2/agents/run\nMETAMUSEUM_AG2_BRIDGE_TIMEOUT_MS=5000\npnpm dev\n```\n\nFor PowerShell:\n\n```powershell\n$env:METAMUSEUM_AG2_BRIDGE_ENABLED=\"1\"\n$env:METAMUSEUM_AG2_BRIDGE_URL=\"http://127.0.0.1:7788/ag2/agents/run\"\n$env:METAMUSEUM_AG2_BRIDGE_TIMEOUT_MS=\"5000\"\npnpm dev\n```\n\n## Safe Smoke\n\nRun the worker tests first:\n\n```bash\npnpm ag2:worker:test\n```\n\nThen run the agent API focused tests:\n\n```bash\nnode --import tsx --test tests/api/agents-run.test.ts\n```\n\nRun the live worker eval artifact check:\n\n```bash\npnpm ag2:worker:eval\npnpm ag2:worker:eval:check\n```\n\nArtifacts:\n\n- `artifacts/agents/ag2-worker-eval-latest.json`\n- `artifacts/agents/runs/ag2-worker-eval-<timestamp>.json`\n\nThe local target may warn when operator sign-off is absent. Production target\nchecks fail without sign-off.\n\nManual API smoke:\n\n```bash\ncurl -X POST http://127.0.0.1:3000/api/agents/run \\\n  -H \"content-type: application/json\" \\\n  -H \"x-request-id: req-ag2-smoke\" \\\n  -H \"traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01\" \\\n  -d \"{\\\"agent\\\":\\\"mercator\\\",\\\"goal\\\":\\\"Review mapping via AG2 worker.\\\",\\\"mappingAssist\\\":{\\\"sourceProvider\\\":\\\"met\\\",\\\"sourceFormat\\\":\\\"csv\\\",\\\"columns\\\":[\\\"Object Title\\\"],\\\"sampleRows\\\":[{\\\"Object Title\\\":\\\"Smoke Object\\\"}]}}\"\n```\n\nPass conditions:\n\n- response `agent` is `mercator`;\n- response `bridge.status` is `used`;\n- `task.approvalRequired` is `true`;\n- `task.inputs.execution.runtime` is `ag2-worker` or AG2-bridge compatible;\n- `task.inputs.ag2Bridge.status` is `used`;\n- response headers include `x-request-id` and `traceparent`;\n- no records are published, merged, imported, or rights-cleared.\n\nFallback smoke:\n\n```bash\nMETAMUSEUM_AG2_BRIDGE_ENABLED=1\nMETAMUSEUM_AG2_BRIDGE_URL=\nnode --import tsx --test tests/api/agents-run.test.ts\n```\n\nPass condition:\n\n- local review still succeeds and `bridge.status` is `fallback`.\n\n## Deployment Rules\n\n- Default production posture is `METAMUSEUM_AG2_BRIDGE_ENABLED=0`.\n- Staging may enable the bridge only when the worker is bound to loopback or a\n  private service address.\n- Do not expose the worker directly to the public internet.\n- Keep `METAMUSEUM_AG2_BRIDGE_TIMEOUT_MS` at or below `5000` unless a reviewed\n  performance test proves a higher value is safe.\n- Treat worker URL changes as a deployment/runbook change that requires human\n  approval.\n- Keep `/api/agents/tasks` editor-gated so bridge output remains review-only.\n\n## Environment Variables\n\n- `METAMUSEUM_AG2_BRIDGE_ENABLED` (default `0`)\n- `METAMUSEUM_AG2_BRIDGE_URL` (default unset; local worker URL is\n  `http://127.0.0.1:7788/ag2/agents/run`)\n- `METAMUSEUM_AG2_BRIDGE_TIMEOUT_MS` (default `5000`, clamped by bridge code)\n- `METAMUSEUM_AG2_WORKER_HOST` (default `127.0.0.1`)\n- `METAMUSEUM_AG2_WORKER_PORT` (default `7788`)\n- `METAMUSEUM_AG2_WORKER_MAX_RECORDS` (default `50`)\n- `METAMUSEUM_AG2_WORKER_MAX_COLUMNS` (default `100`)\n- `METAMUSEUM_AG2_EVAL_TARGET` (default `local`; allowed `local`, `staging`,\n  `production`)\n- `METAMUSEUM_AG2_OPERATOR_NAME` (required for production eval pass)\n- `METAMUSEUM_AG2_OPERATOR_SIGNED_AT` (ISO timestamp; required for production\n  eval pass)\n- `METAMUSEUM_AG2_OPERATOR_SCOPE` (required for production eval pass)\n\n## Rollback\n\nSet:\n\n```bash\nMETAMUSEUM_AG2_BRIDGE_ENABLED=0\n```\n\nThen restart the Next.js process. The app returns to local TypeScript review\nwithout changing the `/api/agents/run` response contract.\n\n## Evidence To Capture\n\nBefore enabling outside local development, record:\n\n- `pnpm ag2:worker:test`\n- `pnpm ag2:worker:eval:check`\n- `node --import tsx --test tests/api/agents-run.test.ts`\n- `pnpm test`\n- `pnpm lint`\n- `pnpm build`\n- a manual smoke response showing `bridge.status: \"used\"` and\n  `approvalRequired: true`\n- rollback confirmation with `bridge.status: \"disabled\"` or `fallback`\n- operator sign-off fields for production: operator, signedAt, and scope\n","sections":[{"level":2,"heading":"Install Deps","anchor":"install-deps"},{"level":2,"heading":"Run Locally","anchor":"run-locally"},{"level":2,"heading":"Health Check","anchor":"health-check"},{"level":2,"heading":"Enable Bridge Locally","anchor":"enable-bridge-locally"},{"level":2,"heading":"Safe Smoke","anchor":"safe-smoke"},{"level":2,"heading":"Deployment Rules","anchor":"deployment-rules"},{"level":2,"heading":"Environment Variables","anchor":"environment-variables"},{"level":2,"heading":"Rollback","anchor":"rollback"},{"level":2,"heading":"Evidence To Capture","anchor":"evidence-to-capture"}],"html":"<h1 id=\"ag2-worker-and-bridge-runbook\">AG2 Worker and Bridge Runbook</h1>\n<p>This runbook covers the local review-only AG2 worker and the disabled-by-default</p>\n<p>Next.js bridge that can delegate Mercator and Janus review execution.</p>\n<p>Service path:</p>\n<ul><li>`services/ag2-worker/`</li></ul>\n<p>Bridge owner:</p>\n<ul><li>`src/services/ag2-bridge.ts`</li></ul>\n<p>What it does:</p>\n<p>  request body.</p>\n<p>  response, HTTP failure, or timeout occurs.</p>\n<ul><li>Exposes `GET /health` for local worker readiness.</li><li>Exposes `POST /ag2/agents/run` for internal, server-side review execution.</li><li>Accepts only Mercator and Janus.</li><li>Preserves the existing `AgentTask` envelope and human approval gate.</li><li>Records trace metadata from `x-request-id`, `traceparent`, and the bridge</li><li>Falls back to local TypeScript review when disabled, missing URL, invalid</li></ul>\n<p>What it must not do:</p>\n<p>  `equivalent` links.</p>\n<ul><li>Publish, merge identities, clear rights, activate imports, or write</li><li>Expose A2A, AG-UI, or LAN/public agent endpoints.</li><li>Accept agents other than Mercator and Janus without new tests and review.</li><li>Run with secrets passed through tool arguments or client-visible schemas.</li></ul>\n<h2 id=\"install-deps\">Install Deps</h2>\n<pre><code>\npnpm ag2:worker:deps\n</code></pre>\n<h2 id=\"run-locally\">Run Locally</h2>\n<pre><code>\npnpm ag2:worker\n</code></pre>\n<p>Default bind:</p>\n<ul><li>`http://127.0.0.1:7788`</li></ul>\n<h2 id=\"health-check\">Health Check</h2>\n<pre><code>\ncurl http://127.0.0.1:7788/health\n</code></pre>\n<p>Expected shape:</p>\n<pre><code>\n{\n  &quot;ok&quot;: true,\n  &quot;service&quot;: &quot;ag2-worker&quot;,\n  &quot;eligibleAgents&quot;: [&quot;mercator&quot;, &quot;janus&quot;],\n  &quot;reviewOnly&quot;: true\n}\n</code></pre>\n<h2 id=\"enable-bridge-locally\">Enable Bridge Locally</h2>\n<p>Keep the worker loopback-only, start the worker, then start the Next app with</p>\n<p>the bridge enabled:</p>\n<pre><code>\npnpm ag2:worker\n</code></pre>\n<p>In the app environment:</p>\n<pre><code>\nMETAMUSEUM_AG2_BRIDGE_ENABLED=1\nMETAMUSEUM_AG2_BRIDGE_URL=http://127.0.0.1:7788/ag2/agents/run\nMETAMUSEUM_AG2_BRIDGE_TIMEOUT_MS=5000\npnpm dev\n</code></pre>\n<p>For PowerShell:</p>\n<pre><code>\n$env:METAMUSEUM_AG2_BRIDGE_ENABLED=&quot;1&quot;\n$env:METAMUSEUM_AG2_BRIDGE_URL=&quot;http://127.0.0.1:7788/ag2/agents/run&quot;\n$env:METAMUSEUM_AG2_BRIDGE_TIMEOUT_MS=&quot;5000&quot;\npnpm dev\n</code></pre>\n<h2 id=\"safe-smoke\">Safe Smoke</h2>\n<p>Run the worker tests first:</p>\n<pre><code>\npnpm ag2:worker:test\n</code></pre>\n<p>Then run the agent API focused tests:</p>\n<pre><code>\nnode --import tsx --test tests/api/agents-run.test.ts\n</code></pre>\n<p>Run the live worker eval artifact check:</p>\n<pre><code>\npnpm ag2:worker:eval\npnpm ag2:worker:eval:check\n</code></pre>\n<p>Artifacts:</p>\n<ul><li>`artifacts/agents/ag2-worker-eval-latest.json`</li><li>`artifacts/agents/runs/ag2-worker-eval-&lt;timestamp&gt;.json`</li></ul>\n<p>The local target may warn when operator sign-off is absent. Production target</p>\n<p>checks fail without sign-off.</p>\n<p>Manual API smoke:</p>\n<pre><code>\ncurl -X POST http://127.0.0.1:3000/api/agents/run \\\n  -H &quot;content-type: application/json&quot; \\\n  -H &quot;x-request-id: req-ag2-smoke&quot; \\\n  -H &quot;traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01&quot; \\\n  -d &quot;{\\&quot;agent\\&quot;:\\&quot;mercator\\&quot;,\\&quot;goal\\&quot;:\\&quot;Review mapping via AG2 worker.\\&quot;,\\&quot;mappingAssist\\&quot;:{\\&quot;sourceProvider\\&quot;:\\&quot;met\\&quot;,\\&quot;sourceFormat\\&quot;:\\&quot;csv\\&quot;,\\&quot;columns\\&quot;:[\\&quot;Object Title\\&quot;],\\&quot;sampleRows\\&quot;:[{\\&quot;Object Title\\&quot;:\\&quot;Smoke Object\\&quot;}]}}&quot;\n</code></pre>\n<p>Pass conditions:</p>\n<ul><li>response `agent` is `mercator`;</li><li>response `bridge.status` is `used`;</li><li>`task.approvalRequired` is `true`;</li><li>`task.inputs.execution.runtime` is `ag2-worker` or AG2-bridge compatible;</li><li>`task.inputs.ag2Bridge.status` is `used`;</li><li>response headers include `x-request-id` and `traceparent`;</li><li>no records are published, merged, imported, or rights-cleared.</li></ul>\n<p>Fallback smoke:</p>\n<pre><code>\nMETAMUSEUM_AG2_BRIDGE_ENABLED=1\nMETAMUSEUM_AG2_BRIDGE_URL=\nnode --import tsx --test tests/api/agents-run.test.ts\n</code></pre>\n<p>Pass condition:</p>\n<ul><li>local review still succeeds and `bridge.status` is `fallback`.</li></ul>\n<h2 id=\"deployment-rules\">Deployment Rules</h2>\n<p>  private service address.</p>\n<p>  performance test proves a higher value is safe.</p>\n<p>  approval.</p>\n<ul><li>Default production posture is `METAMUSEUM_AG2_BRIDGE_ENABLED=0`.</li><li>Staging may enable the bridge only when the worker is bound to loopback or a</li><li>Do not expose the worker directly to the public internet.</li><li>Keep `METAMUSEUM_AG2_BRIDGE_TIMEOUT_MS` at or below `5000` unless a reviewed</li><li>Treat worker URL changes as a deployment/runbook change that requires human</li><li>Keep `/api/agents/tasks` editor-gated so bridge output remains review-only.</li></ul>\n<h2 id=\"environment-variables\">Environment Variables</h2>\n<p>  `http://127.0.0.1:7788/ag2/agents/run`)</p>\n<p>  `production`)</p>\n<p>  eval pass)</p>\n<ul><li>`METAMUSEUM_AG2_BRIDGE_ENABLED` (default `0`)</li><li>`METAMUSEUM_AG2_BRIDGE_URL` (default unset; local worker URL is</li><li>`METAMUSEUM_AG2_BRIDGE_TIMEOUT_MS` (default `5000`, clamped by bridge code)</li><li>`METAMUSEUM_AG2_WORKER_HOST` (default `127.0.0.1`)</li><li>`METAMUSEUM_AG2_WORKER_PORT` (default `7788`)</li><li>`METAMUSEUM_AG2_WORKER_MAX_RECORDS` (default `50`)</li><li>`METAMUSEUM_AG2_WORKER_MAX_COLUMNS` (default `100`)</li><li>`METAMUSEUM_AG2_EVAL_TARGET` (default `local`; allowed `local`, `staging`,</li><li>`METAMUSEUM_AG2_OPERATOR_NAME` (required for production eval pass)</li><li>`METAMUSEUM_AG2_OPERATOR_SIGNED_AT` (ISO timestamp; required for production</li><li>`METAMUSEUM_AG2_OPERATOR_SCOPE` (required for production eval pass)</li></ul>\n<h2 id=\"rollback\">Rollback</h2>\n<p>Set:</p>\n<pre><code>\nMETAMUSEUM_AG2_BRIDGE_ENABLED=0\n</code></pre>\n<p>Then restart the Next.js process. The app returns to local TypeScript review</p>\n<p>without changing the `/api/agents/run` response contract.</p>\n<h2 id=\"evidence-to-capture\">Evidence To Capture</h2>\n<p>Before enabling outside local development, record:</p>\n<p>  `approvalRequired: true`</p>\n<ul><li>`pnpm ag2:worker:test`</li><li>`pnpm ag2:worker:eval:check`</li><li>`node --import tsx --test tests/api/agents-run.test.ts`</li><li>`pnpm test`</li><li>`pnpm lint`</li><li>`pnpm build`</li><li>a manual smoke response showing `bridge.status: &quot;used&quot;` and</li><li>rollback confirmation with `bridge.status: &quot;disabled&quot;` or `fallback`</li><li>operator sign-off fields for production: operator, signedAt, and scope</li></ul>","updatedAt":"2018-10-20T01:46:40.000Z","checksum":"50efcd4e3318ffe600fb0a822d61e87180e8799114d1bdf07fbf917b907a992b","checksumPrefix":"50efcd4e3318","anchorCount":9,"lineCount":208,"rawUrl":"/api/docs/content?path=ops%2Fag2-worker.md","htmlUrl":"/docs?doc=ops%2Fag2-worker.md","apiUrl":"/api/docs/content?path=ops%2Fag2-worker.md"}