N NOIR
DOCUMENTATION v0.3
01 / QUICKSTART

Build your first agent.

Install one package, create one file, and keep ownership of every important choice.

npm install @noir-agent/agent

A useful agent in one file

import { noir } from '@noir-agent/agent'
import { slack } from '@noir-agent/agent/channels/slack'

export default noir({
  model,
  personality: 'Funny, direct, and deeply useful.',
  channels: { slack: slack() },
  database: db,
  memory,
  sandbox,
  plugins: [stripe({ client: stripeClient })],
})
No Noir API key. Noir runs in your process. You only configure the services you choose.
02 / MENTAL MODEL

Your code is the product.

Noir is a reliability layer, not an agent cloud. It wraps your agent with durable execution, policy, approvals, delivery, and observability.

CHANNELSlack event
NOIRverify + persist
YOUR AGENTmodel + tools
NOIRdurable send
Bring the brain

Use OpenRouter, the AI SDK, an agent framework, or a function.

Bring the state

Pass your Drizzle database, memory client, and sandbox.

Bring the services

Add Stripe, GitHub, MCP, or your own plugins.

Own the runtime

Deploy the same code to any Node-compatible host.

03 / CONFIGURATION

One tree. No ceremony.

The top-level object mirrors the architecture of a real agent. SDK-native values stay native.

KEYWHAT GOES THERE
modelYour model or model adapter
channelsSlack, Telegram, email, or custom adapters
databaseYour database-backed Noir store
memoryYour memory implementation
sandboxYour code-execution environment
pluginsProduct capabilities such as Stripe
toolsAgent-callable functions
04 / SLACK

Meet users where work happens.

The Slack adapter verifies requests, normalizes mentions and direct messages, preserves threads, receives files, and renders approvals.

import { slack } from '@noir-agent/agent/channels/slack'

channels: {
  slack: slack({
    token: process.env.SLACK_BOT_TOKEN,
    signingSecret: process.env.SLACK_SIGNING_SECRET,
  }),
}
  1. Create a Slack app and add app_mention and message.im.
  2. Point Event Subscriptions to https://your-host/webhooks/slack.
  3. Add the Slack token and signing secret to your host.
  4. Invite the bot and mention it.
05 / TOOLS & PLUGINS

Effects are explicit.

A tool declares what it can change. Noir can allow reads, require approval for writes, and audit every side effect.

const issueRefund = tool({
  description: 'Refund a Stripe payment',
  effect: 'destructive',
  input: z.object({ paymentId: z.string() }),
  execute: ({ paymentId }) => stripe.refunds.create({
    payment_intent: paymentId,
  }),
})

Plugins package related tools, routes, services, and lifecycle hooks. Use Stripe, GitHub, PostHog, MCP, or create a plain plugin in your own codebase.

06 / MEMORY

Memory is infrastructure.

Pass an implementation directly. Noir supplies the lifecycle and retrieval seams; your provider owns the data.

import { supermemory } from '@noir-agent/agent/memory/supermemory'

export default noir({
  memory: supermemory({ client }),
})

A custom memory adapter can wrap pgvector, Redis, a filesystem, or an internal service.

07 / SANDBOX

Bring your own computer.

Sandbox is a first-class boundary because execution policy, files, timeout, and cleanup affect the whole agent.

export default noir({
  sandbox: {
    create: ({ executionId }) => mySandbox.start(executionId),
    execute: (box, command) => box.run(command),
    dispose: (box) => box.stop(),
  },
})

Use E2B, Daytona, Modal, Docker, a VM pool, or an internal executor. Noir does not proxy or own the sandbox.

08 / LOOPS & APPROVALS

Long work survives.

Noir persists each run, tool result, approval, and outbound delivery so a restart does not restart the user's intent.

const draft = await noir.run('write-post', writePost)

const approved = await noir.ask({
  title: 'Open this pull request?',
  details: draft.summary,
})

if (approved) await noir.run('open-pr', openPullRequest)
Bounded tool loops

Cap steps, time, retries, and output.

Human approvals

Pause safely and resume durable state.

Schedules

Run recurring work with context.

Steering

Accept direction while work runs.

09 / STORAGE

Your database, not ours.

Use the in-memory store locally, then provide a Postgres-backed store for durable production runs.

import { postgresStore } from '@noir-agent/agent/store/postgres'

const database = postgresStore({ db })
await database.migrate()

The store persists inbox events, run state, outbox delivery, approvals, schedules, leases, and idempotent step results.

10 / PRODUCTION

Ship the Node app you own.

npx noir start ./dist/agent.js --port 3000
  • Use durable storage and run migrations.
  • Keep credentials in your host's secret manager.
  • Expose HTTPS webhook routes without login protection.
  • Run noir doctor before receiving traffic.
  • Forward events to your observability stack.
  • Test duplicate delivery and approval replay.
Read the full runtime reference on GitHub
ON THIS PAGEQuickstartInstallOne-file agentNoir API key