AI agents
Belgie gives an agent one run_code tool for executing complete JavaScript, TypeScript, or TSX
modules in an embedded Deno runtime. The tool is available through the supported Pydantic AI and
LangChain integrations.
The model supplies module source, not a JavaScript fragment. Belgie executes the module, calls its exported function, and returns that function's JSON-compatible value as the tool result.
When to use run_code
Use run_code when the model needs an npm or JSR package, a browser-style JavaScript API, parallel
JavaScript requests, or a transformation that is clearer in TypeScript than in Python. The model
supplies a complete module rather than a fragment:
export default async function run(value: string): Promise<string> {
return value.trim().toUpperCase();
}
The returned value becomes the tool result. It must be JSON-serializable. Use Deno-style imports
such as npm:pkg@version, jsr:@scope/pkg@version, or a full URL.
Agent lifecycle
Each agent invocation creates a BelgieRuntimeSession, executes scripts in a restricted runtime,
and closes the session when the invocation finishes. A script that imports npm:@belgie/render
requests a separate host-mediated render pass; the model-visible script runtime does not receive the
renderer's broader Vite permissions.
sequenceDiagram
participant Agent
participant Sandbox as Belgie sandbox
participant Renderer as Optional renderer
Agent->>Sandbox: run_code(module)
Sandbox-->>Agent: JSON result
Agent->>Sandbox: run_code(render module)
Sandbox->>Renderer: render request
Renderer-->>Agent: self-contained HTML
The session is temporary by default. Passing an Environment supplies a workspace and dependency
set for the invocation. Passing a caller-owned runtime reuses that runtime, but Belgie cannot
mediate inline rendering through a custom runtime.
Sandbox boundaries
The default agent session is intentionally narrower than a general-purpose Deno runtime:
- Network access is disabled unless the integration's runtime configuration allows it.
- Script reads are limited to the session workspace.
- Host
/etcand/proc, system calls, and FFI are not exposed to model-authored scripts. - Return values cross the Python/framework boundary as JSON-compatible values.
- External agent tools are not directly available inside the JavaScript sandbox.
Not a host isolation guarantee
Permissions define what the embedded runtime can access, but your application still controls which code and dependencies it supplies. Do not grant broad permissions to untrusted code without reviewing the resulting boundary.
The default permissions are an execution boundary for model-authored scripts, not a replacement for application-level review of prompts, dependencies, or host integrations.
Configure the session
BelgieCapability and BelgieMiddleware share these options; identifier names follow each framework:
| Option | Default | Purpose |
|---|---|---|
max_retries |
3 |
Retry invalid run_code calls through the framework. |
timeout |
None |
Cancel a script after the given number of seconds. |
instructions |
None |
Append guidance to the built-in run_code instructions. |
dangerously_replace_instructions |
None |
Replace the built-in instructions completely. |
runtime |
None |
Reuse a caller-owned Runtime. |
environment |
None |
Use a caller-owned or newly-created Environment. |
runtime_options |
None |
Configure the session-created runtime. |
defer_loading |
False |
Expose load_belgie first and make run_code available after loading. |
id (Pydantic AI) |
None |
Stable Pydantic AI identifier used for deferred loading; Belgie defaults it to belgie. |
capability_id (LangChain) |
None |
Stable Belgie identifier used for deferred loading; Belgie defaults it to belgie. |
runtime cannot be combined with environment or runtime_options. The two instruction options
are mutually exclusive.
Use instructions to append application-specific guidance while retaining Belgie's module and
sandbox contract. Use dangerously_replace_instructions only when the application reproduces the
parts of that contract the model still needs.
Synchronous and asynchronous agents
The Pydantic AI integration supports synchronous and asynchronous agent runs. LangChain supports
invoke() and ainvoke(). The Belgie session follows the surrounding framework lifecycle, so close
or await the agent run before disposing of a caller-owned environment or runtime.
Inline React widgets
An agent can return a self-contained HTML document by returning render(...) from a TSX module:
import { render } from "npm:@belgie/render";
function Widget() {
return <main>Hello from Belgie</main>;
}
export default function run() {
return render({ widget: <Widget />, plugins: [] });
}
See @belgie/render for the static-analysis and renderer constraints.
This inline renderer is separate from path-based MCP Apps. Use MCP Apps when the
widget is part of a Python server project; use render(...) when an agent should return one HTML
document as its ordinary tool result.
Renderer plugins are privileged
A nonempty plugins value is evaluated again in the host-mediated renderer. Plugin factories,
hooks, and their imports run with the renderer's broader permissions. Treat them as reviewed
application code and use plugins: [] for untrusted agent-authored widgets.
Choose an integration
- Use Pydantic AI when your agent is built with Pydantic AI capabilities.
- Use LangChain when your agent uses LangChain middleware.
- Use Runtime directly when no agent framework is involved.