> ## Documentation Index
> Fetch the complete documentation index at: https://docs.plurai.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Node agents

> Simulate a TypeScript or JavaScript agent in its own runtime through the Node bridge: Mastra, Vercel AI SDK, LangGraph.js, OpenAI Agents JS or a custom loop.

An agent written in TypeScript or JavaScript keeps running in Node. The harness, `simulate.py`, stays in Python
and drives your agent through a **bridge** child process, so the mock environment, scenarios, evals and report
are the same as for a Python agent.

The scan picks the bridge automatically for every Node agent its preflight accepts:

* Mastra
* Vercel AI SDK
* LangGraph.js
* OpenAI Agents JS
* A custom agent loop

## Requirements

A bridge setup needs two runtimes on your machine:

| Runtime | Why |
| - | - |
| Python with the `plurai` SDK in a virtual environment | Runs the harness, `simulate.py`. See [Install the SDK](https://docs.plurai.ai/sdk/install.md). |
| Node 22.15 or newer, with `npm` | Runs your agent in the bridge child. The bridge needs `module.registerHooks`, which landed in Node 22.15 and 23.5. |

Your agent's own dependencies must already be installed (its `node_modules`). Installing them is up to you; the
bridge never installs into your project.

## What the bridge installs, and where

Everything the bridge writes lives under the plugin's work folder, `plurai_sim/`, in your project:

| Path | What it is | Commit it? |
| - | - | - |
| `plurai_sim/bridge/bridge.map.json` | The map from each external call your agent makes to a mocked tool, each entry with the file and line where your code makes the call. | Yes |
| `plurai_sim/bridge/entry.mjs` | The entry the bridge calls each turn. It imports your agent's construction module and serves a turn the way your production route does. | Yes |
| `plurai_sim/bridge/replace/*.mjs` | In-memory replacements for your agent's own persistence (conversation memory, a checkpointer, a cache), when the map needs them. | Yes |
| `plurai_sim/bridge/host.py`, `plurai_sim/bridge/runtime/` | The bridge runtime, copied unchanged from the plugin. | Yes |
| `plurai_sim/bridge/runtime/node_modules/` | The runtime's pinned dependencies, installed with `npm ci`. | No. The managed `.gitignore` block excludes it. |

The bridge never reads or changes your `package.json` or your project's `.npmrc`. Its one write outside the
work folder is npm's cache under `~/.npm`.

If the runtime install fails behind a proxy or private registry, set the registry or proxy in `~/.npmrc`. Your
project's `.npmrc` does not apply to the bridge's install.

## How your agent's calls are mocked

The scan maps each external system your agent calls at the deepest boundary below your business logic:

| Seam | Used when |
| - | - |
| Client package | The default. Your agent imports a client package and the call path (for example `client.refunds.create`) names the operation. |
| Module facade | One module of your agent funnels the external calls and holds no branching logic. |
| HTTP | Your agent calls with `fetch` or `http` and no client package, or its client is refused below and speaks HTTP. |
| Framework infrastructure | Your agent's own persistence that no tool reads, such as conversation memory or a checkpointer, replaced in memory. |

Anything the map does not route fails closed at run time. An unmapped call, a refused shape, or a call to a host
you did not declare voids the turn as a harness fault that names it, even when your agent catches the error.

Conversation history stays your agent's own. Each turn the bridge sends the thread id and the new user message
only, and your agent keeps history keyed on the thread, as it does in production.

## Refused runtimes and shapes

The bridge refuses these by name, with the reason and a remedy. It never works around them.

| Refused | Why |
| - | - |
| Bun, Deno | No bridge child ships for these runtimes yet. |
| A Windows host | The bridge channel needs POSIX file-descriptor passing. |
| Yarn Plug'n'Play | The bridge resolves modules through `node_modules`. |
| A `worker_threads` worker a turn starts | The bridge cannot follow calls into a worker. The preflight warns early; the runtime refuses it when a turn starts one. |
| A raw SQL driver (`pg`, `mysql2`, `postgres`, `better-sqlite3`, …) with no data-access module of your own | One call path serves every query, so no call names a tool. With your own data-access module in front of the driver, that module is mapped instead. |
| Any other language (Go, Java, Ruby, …) | Only the Node bridge child ships. |

Some client shapes cannot be mapped at the package level and are mapped at another seam instead. For example,
AWS SDK `send(new XCommand())` calls are mapped at the HTTP level, and query builders such as `knex`,
`drizzle-orm`, `kysely` or `@supabase/supabase-js` are mapped at HTTP or at your own data-access module.

A NestJS app may need a build before the bridge can import it, and a Next.js app's runtime APIs can be refused.
The preflight says so with the remedy.

## How a Run reads bridge outcomes

* A fail-closed event, a mocked call the harness could not serve, or the child's death is a **harness fault**.
  The scenario is void, and the log tail is in its error record.
* An error your agent's own code threw is a **failed trial**, owned by your agent.
* A provider failure is recorded as provider infrastructure, not as your agent's failure.

Each scenario process runs one Node child, about 100–200 MB. Cap concurrency to fit your machine's memory.

## Next steps

> [card] [Scan your agent](https://docs.plurai.ai/guides/scan-your-agent.md)
>
> Generate the harness and the bridge map.

> [card] [Run the simulation](https://docs.plurai.ai/guides/run-the-simulation.md)
>
> Score your agent across the suite.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.