Quick Start
This page takes you from nothing to a governed agent in a few minutes. Everything here is copy-paste; the snippets mirror the patterns the SDK's own test suite exercises.
1. Install
pnpm add @agent-assembly/sdk
# or
npm install @agent-assembly/sdk
# or
yarn add @agent-assembly/sdk
The package ships dual ESM/CJS entries and selects a prebuilt native binding for your
platform during postinstall, so there is no extra build step for typical consumers.
The public surface (initAssembly, withAssembly) is stabilizing but may change
between pre-releases. Pin an exact version for reproducible installs:
npm install @agent-assembly/sdk@0.0.1-rc.4
2. Make sure a gateway is reachable
The SDK enforces policy by talking to an Agent Assembly gateway. You have two options:
- Let the SDK auto-start a local gateway (simplest). If you have the
aasmbinary on yourPATH(npm install -g @agent-assembly/cli), a zero-configinitAssembly()will probehttp://localhost:7391and start a local gateway for you if nothing is running. - Point at a gateway you already run. Set
AAASM_GATEWAY_URL(andAAASM_API_KEYif it requires auth), or passgatewayUrlexplicitly.
See Configuration for the full resolution order.
3. Govern your first agent with withAssembly
withAssembly wraps a map of tools so the local policy is enforced before each one
runs: an allowed call executes normally, while a denied call throws a
PolicyViolationError and the tool body never runs. Pick your framework below —
each tab is the governance-wiring excerpt from that framework's runnable
example, kept in
lock-step with the example by a CI drift check so a snippet can never rot.
LangChain.js is the validated path; the remaining frameworks are experimental.
The excerpts are ESM / TypeScript; under CommonJS, swap the import for
const { withAssembly } = require("@agent-assembly/sdk").
- LangChain.js
- Custom (no framework)
- OpenAI (Node) (Experimental)
- Vercel AI SDK (Experimental)
- LangGraph.js (Experimental)
- Mastra (Experimental)
const tools = withAssembly(
{
get_weather: {
execute: async (args: Record<string, unknown>) => TOOLS.get_weather(args).output
},
delete_file: {
execute: async (args: Record<string, unknown>) => TOOLS.delete_file(args).output
}
},
{ gatewayClient: createPolicyGatewayClient(), agentId: "langchain-js-example-agent" }
);
const tools = withAssembly(
{
read_file: {
execute: async (args: Record<string, unknown>) =>
readFile(typeof args.path === "string" ? args.path : "").output
},
write_file: {
execute: async (args: Record<string, unknown>) =>
writeFile(
typeof args.path === "string" ? args.path : "",
typeof args.content === "string" ? args.content : ""
).output
}
},
{ gatewayClient: createPolicyGatewayClient(), agentId: "custom-tool-policy-agent" }
);
const tools = withAssembly(
{
search_web: {
execute: async (args: Record<string, unknown>) =>
searchWeb(typeof args.query === "string" ? args.query : "").output
},
send_email: {
execute: async (args: Record<string, unknown>) =>
sendEmail(
typeof args.to === "string" ? args.to : "",
typeof args.subject === "string" ? args.subject : ""
).output
}
},
{ gatewayClient: createPolicyGatewayClient(), agentId: "openai-node-example-agent" }
);
// withAssembly wraps each tool's `execute`, keying the policy by the map key.
// The Vercel AI SDK tools run unchanged; only governance is layered on top.
const tools = withAssembly(
{
get_weather: getWeatherTool,
send_email: sendEmailTool,
},
{ gatewayClient: createPolicyGatewayClient(), agentId: "vercel-ai-example-agent" }
);
/**
* Build governed tools once, then call them from inside graph nodes.
* withAssembly enforces the local policy before each tool runs.
*/
function buildGovernedTools() {
return withAssembly(
{
search_docs: {
execute: async (args: Record<string, unknown>) => TOOLS.search_docs(args).output,
},
execute_shell: {
execute: async (args: Record<string, unknown>) => TOOLS.execute_shell(args).output,
},
},
{ gatewayClient: createPolicyGatewayClient(), agentId: "langgraph-js-example-agent" }
);
}
// Wrap the Mastra tools with withAssembly. Each governed entry delegates to the
// real Mastra tool's execute, so the policy is enforced before the tool runs.
const tools = withAssembly(
{
get_stock_price: {
execute: async (args: Record<string, unknown>) => runMastraTool(getStockPriceTool, args),
},
place_trade: {
execute: async (args: Record<string, unknown>) => runMastraTool(placeTradeTool, args),
},
},
{ gatewayClient: createPolicyGatewayClient(), agentId: "mastra-example-agent" }
);
4. What to expect
- Allow. The tool runs normally and returns its result. A governance event is recorded in the audit trail.
- Deny. The wrapped
invoke()rejects with aPolicyViolationErrorwhose message includes the tool name and the gateway's reason — the tool body never runs. - Pending (needs approval). The call waits up to
langchain.approvalTimeoutMs(default applies if unset) for a human decision, then either proceeds or rejects.
That deny-on-policy behavior is the whole point: a denied tool call throws instead of executing. If you want to watch what would be blocked without actually blocking it while you tune policy, register the agent in observe mode:
const ctx = await initAssembly({
agentId: "demo",
enforcementMode: "observe", // dry-run: actions proceed, violations recorded as shadow events
langchain: { tools: { searchWeb } }
});
Next steps
- Guides — the full LangChain walkthrough, the low-level
withAssemblywrapper, experimental frameworks, and how to handle allow/deny decisions and errors. - Configuration — every
AssemblyConfigfield and the gateway/API-key resolution precedence. - Core Concepts — what the native binding, the
adapter registry, and the
initAssemblylifecycle actually do.