
Security News
Agent Baseline Publishes Security Reference Architecture for Software Factories
Agent Baseline’s new reference architecture shows how to secure software factories with four boundaries enforced outside the AI agent.
@archxflow/bridge
Advanced tools
Connects the FreeCAD and Blender on an architect's machine to Agentic Arch in the cloud.
Connects the FreeCAD and Blender already installed on an architect's machine to Agentic Arch running in the cloud, so the AI can build real geometry there instead of generating a picture of it.
Architect's machine Cloud (Cloud Run)
┌────────────────────────────┐ ┌──────────────────────────┐
│ FreeCAD GUI ── XMLRPC :9875│ │ NestJS + Vertex (Gemini) │
│ Blender GUI ── TCP :9876│ │ BridgeGateway (wss) │
│ ▲ │ │ device registry │
│ │ │ wss │ job dispatch │
│ archxflow-bridge run ──────────┼────────────►│ chat tool loop │
│ (outbound only) │ ticketed │ │
└────────────────────────────┘ └──────────────────────────┘
The agent dials out. Nothing listens on the architect's machine, so there is no port to forward, no firewall rule, and no inbound surface — which is also why this works from a laptop on hotel wifi.
Published as @archxflow/bridge. It needs Node 22 or newer and has no runtime dependencies of its own.
npm install -g @archxflow/bridge
In the web app, generate a pairing code, then on the machine with FreeCAD:
archxflow-bridge pair ABCD-EFGH --url https://your-cloud
archxflow-bridge run
Before it is published, build it from this repository instead — the commands
are the same with node dist/index.js in place of archxflow-bridge:
cd agent
npm install # typescript only; the agent itself has no runtime deps
npm run build # compiles dist/ and copies cad/freecad/*.py into scripts/
pair swaps the code for a long-lived device token and stores it in the
platform's own per-user config directory with 0600 permissions. The cloud
keeps only a SHA-256 of it, so a leaked server database cannot be replayed.
Check what the agent can see at any time:
archxflow-bridge status
The cloud model can write arbitrary Python into FreeCAD and Blender. That is the point of the bridge, and it is also remote code execution on someone's workstation, so the two categories are treated differently:
freecad.build, freecad.sheets, freecad.presentation, blender.render, all the *.status/screenshot/scene reads | Run unattended. The Python is the platform's own, bundled with this package. The cloud picks which script runs, never what is in it. |
freecad.exec, blender.exec | Prompt. The source is printed in full and someone on the machine answers y / a (allow this verb for the rest of the run) / N. |
────────────────────────────────────────────────────────────────────────
Agentic Arch wants to run Python inside FreeCAD
Why: measure the clear width of the stair well
────────────────────────────────────────────────────────────────────────
│ import FreeCAD
│ doc = FreeCAD.ActiveDocument
│ print(doc.getObject('Stairwell').Shape.BoundBox)
────────────────────────────────────────────────────────────────────────
[y] run once [a] always allow this verb [N] decline :
--bypass turns the prompt off:
archxflow-bridge run --bypass
Do that only where you trust the whole pipeline into the model. A prompt
injection in an uploaded bye-law PDF or a survey drawing reaches the same tool
the architect does, and with --bypass there is nothing between it and this
machine. The agent announces the mode at startup and reports it to the cloud, so
the web app can show which machines are unattended.
With no TTY attached (a service, a container) and no --bypass, code jobs are
declined rather than silently run.
Each driver prefers a running GUI and falls back to a headless process:
GUI (:9875 / :9876) | Headless | |
|---|---|---|
freecad.build | yes | FreeCADCmd |
freecad.sheets | required | — TechDraw builds view geometry on the Qt event loop |
freecad.presentation | required | — viewport captures need a window |
blender.render | yes | blender --background |
A job that needs a GUI fails with that reason rather than quietly producing an empty sheet.
Jobs run in the agent's work directory, laid out the way build.py expects
(it derives the project root from its own path):
<config dir>/work/cad/freecad/*.py ← bundled from the repo at build time
<config dir>/work/cad/out/ ← model.json in, everything else out
Whatever a job produces is uploaded to the cloud and attached to the job, up to 64 MB per file and 256 MB per job. Anything larger is left on disk and reported.
agent.json in the config directory, or flags, or environment:
--url, AGENTIC_ARCH_URL | Cloud base URL |
AGENTIC_ARCH_TOKEN | Device token, for a container that cannot pair interactively |
--bypass | Run code without prompting |
--workDir | Where builds happen |
--freecadCmd, FREECAD_CMD | FreeCADCmd path, if it is somewhere unusual |
--blenderCmd, BLENDER_CMD | Blender path |
Config directory: %APPDATA%\AgenticArch · ~/Library/Application Support/AgenticArch ·
$XDG_CONFIG_HOME/agentic-arch.
Revoke in the web app (DELETE /api/bridge/devices/:id). The record is
tombstoned and any live socket is closed immediately, so a stolen laptop stops
being able to run jobs the moment the button is pressed, not at the end of some
token lifetime. archxflow-bridge unpair only clears the local copy — it does not
tell the cloud to stop trusting it.
src/protocol.ts is a verbatim copy of backend/src/bridge/bridge.protocol.ts
and is refreshed by npm run build. It is type-only and dependency-free so the
same file compiles on both sides.
The agent has no runtime dependencies — Node 22's native WebSocket,
fetch and FormData, a hand-rolled XML-RPC client for FreeCAD (about forty
lines, because the addon accepts six methods), and a raw TCP client for
Blender's unframed JSON.
Settings → Machines in the studio (/settings/machines) does the cloud half
of this: it mints the pairing code, shows the three commands with the code and
your cloud URL already filled in, and lists every paired machine with what is
running on it. The panel closes itself the moment a machine pairs against the
code, so there is no "did that work?" step.
The same page is where a machine is revoked. Revoking closes its live socket
immediately — archxflow-bridge unpair only clears the local copy of the token and
does not tell the cloud to stop trusting it.
Beyond the named build verbs, the bridge passes the whole surface of both applications through, so the cloud can do anything the architect's own MCP client can:
| Verb | Reaches |
|---|---|
agent.capabilities | What both apps expose right now, with a read-only flag per method |
freecad.rpc | Any FreeCAD RPC method — create_object, edit_object, delete_object, insert_part_from_library, run_fem_analysis, execute_code, and the rest |
blender.command | Any Blender addon command, including the optional Polyhaven, Sketchfab, PolyPizza and Hyper3D/Hunyuan handlers when that machine has them enabled |
Blender's list is discovered, not hardcoded: agent.capabilities asks the
addon itself, so handlers that are switched off do not appear and a new addon
release does not need an agent release.
FreeCAD arguments are encoded as real XML-RPC values, so structs and arrays
round-trip — create_object(doc, {Name, Type, Properties: {...}}) works, which
is what makes the passthrough genuinely complete rather than string-only.
Exposing everything does not mean asking for nothing. Because one verb now
covers both list_documents and execute_code, the gate looks at the payload:
Reads — get_*, search_*, poll_*, list_documents, ping | run unattended |
Everything else — creating or editing objects, deleting, FEM runs, asset downloads and generation, execute_code | prompts, showing the method name and its arguments |
"Always allow" is scoped to the method, not the verb — approving
freecad.rpc:get_objects for the session does not silently approve
freecad.rpc:execute_code. --bypass still skips the lot.
Every bridge route is guarded, and the guard defaults to the strictest class — a route added later without a decorator refuses rather than inheriting an open door.
| Route class | Routes | Credential |
|---|---|---|
| agent | POST /bridge/session, POST /bridge/artifacts/:jobId | The device token. An agent has no operator credential and never needs one. |
| pairing | POST /bridge/pair | None — the code is the credential: single use, ten minutes, ~2.8e11 combinations. Rate-limited to 10 failures per address per 10 minutes. |
| operator | everything else — pairing-codes, devices, jobs, artifact download | See below. |
The WebSocket upgrade is not a route: it is authenticated by the single-use ticket, which is itself minted only from a valid device token.
There are no user accounts yet, so this cannot check who — only that the
caller got past something. It fails closed: an unconfigured production
deployment refuses, rather than serving POST /bridge/pairing-codes to the open
internet. Pick one:
BRIDGE_ADMIN_TOKEN=… | Callers send it as Authorization: Bearer …. |
BRIDGE_TRUSTED_PROXY=true | Accept a request carrying an IAP identity header. Only set this when the service cannot be reached except through IAP — the header is trivially forged by anyone who can hit the container directly, so this is opt-in rather than assumed. |
BRIDGE_ALLOW_UNAUTHENTICATED=true | No check at all. Logs a warning at startup. For a private network you control. |
In development (NODE_ENV is not production) loopback is allowed, so the
local two-server setup keeps working with nothing configured. That exemption is
never granted in production.
If IAP fronts the whole service, it rejects the agent's Authorization: Bearer aab_… at the edge, before any of this runs — the agent would never connect.
Reaching a deployment like that needs the agent paths exposed outside IAP (a
second service, or an IAP path exclusion), which is infrastructure rather than
code.
dist/ the compiled agent — one file, no dependencies
scripts/ build.py, sheets.py, presentation.py, copied from cad/freecad at build time
scripts/ is not optional. jobs.ts loads it from ../scripts at runtime, so a
package built without it installs cleanly and then fails every build job with
"build.py is not bundled with this agent". Both directories are listed in
files; check with npm pack --dry-run before publishing.
Neither directory is committed — npm run build regenerates both, and prepack
runs it so npm publish cannot ship a stale one.
FAQs
Connects the FreeCAD and Blender on an architect's machine to Agentic Arch in the cloud.
The npm package @archxflow/bridge receives a total of 3 weekly downloads. As such, @archxflow/bridge popularity was classified as not popular.
We found that @archxflow/bridge demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
Agent Baseline’s new reference architecture shows how to secure software factories with four boundaries enforced outside the AI agent.

Security News
arXiv now limits authors to two submissions a month as AI slop overwhelms moderators, delays good papers, and sparks debate over applying the limit to everyone.

Research
/Security News
A new GhostAction wave hits hundreds of GitHub repos, expanding CI/CD secret theft to cloud and AI credentials in source code and git history.