Agent Toolkit
The Notiflows agent toolkit (@notiflows/agent-toolkit) turns your published notiflows into typed, callable tools for your own AI agents — Vercel AI SDK, OpenAI function calling, and LangChain.
The agent toolkit (@notiflows/agent-toolkit) exposes your notiflows as typed, callable tools for AI agents. Where the MCP server lets an editor manage notiflows, the toolkit lets your own agents use Notiflows at runtime — sending the right notification, to the right people, with a schema-safe payload, where every send is attributed and auditable.
Each published notiflow in your project becomes a typed tool (e.g. trigger_welcome_series), alongside a generic trigger_notiflow tool that takes the handle as an argument. The toolkit runs inside your agent, on your model — the account token authorizes API calls server-side and is never exposed to the LLM.
npm i @notiflows/agent-toolkitCreate the toolkit
import { createNotiflowsToolkit } from "@notiflows/agent-toolkit";
const toolkit = createNotiflowsToolkit({
accountToken: process.env.NOTIFLOWS_TOKEN!, // nf_at_...
project: "acme",
});| Option | Required | Description |
|---|---|---|
accountToken | yes | Notiflows account token (nf_at_...). |
project | yes | Project slug. |
baseUrl | no | Management API base (defaults to https://api.notiflows.com/management/v1). |
notiflows | no | An allowlist of handles, or a (notiflow) => boolean predicate. Omit to expose all published notiflows. |
Tool arguments
Every trigger tool takes the same arguments — provide recipients or a topic:
| Argument | Description |
|---|---|
recipients | Users to notify (provide this or topic). Each recipient is external_id (required) plus optional email, phone, first_name, last_name — used to auto-create the user if they don't exist yet. |
topic | Topic name — notifies all of its subscribers (provide this or recipients). |
data | Template variables, available in the notification as data.*. |
actor | The user who caused the action ({ external_id }), available as actor.*. |
The generic trigger_notiflow tool also takes handle, plus an optional draft ("published" — the default — or "draft" to test the current unpublished version).
Vercel AI SDK
import { generateText } from "ai";
import { openai } from "@ai-sdk/openai";
import { createNotiflowsToolkit } from "@notiflows/agent-toolkit";
import { toAISDKTools } from "@notiflows/agent-toolkit/ai-sdk";
const toolkit = createNotiflowsToolkit({
accountToken: process.env.NOTIFLOWS_TOKEN!,
project: "acme",
});
const tools = await toAISDKTools(await toolkit.getTools());
await generateText({
model: openai("gpt-4o"),
prompt: "Email jane@acme.com the welcome series; her id is user_42.",
tools, // trigger_welcome_series, trigger_order_shipped, ... + trigger_notiflow
});OpenAI function calling
import OpenAI from "openai";
import { createNotiflowsToolkit, toOpenAITools } from "@notiflows/agent-toolkit";
const toolkit = createNotiflowsToolkit({ accountToken: process.env.NOTIFLOWS_TOKEN!, project: "acme" });
const { tools, execute } = toOpenAITools(await toolkit.getTools());
const completion = await new OpenAI().chat.completions.create({
model: "gpt-4o",
messages,
tools,
});
for (const call of completion.choices[0].message.tool_calls ?? []) {
const result = await execute(call.function); // { notiflow_run_id }
}LangChain
import { toLangChainTools } from "@notiflows/agent-toolkit/langchain";
const tools = await toLangChainTools(await toolkit.getTools()); // DynamicStructuredTool[]Framework-agnostic
getTools() returns plain tool descriptors you can wire into any framework:
const tools = await toolkit.getTools(); // [{ name, description, inputSchema, execute }]
await tools[0].execute({
recipients: [{ external_id: "user_42" }],
data: { plan: "pro" },
});Human-in-the-loop
requireHumanInput triggers an approval notiflow (typically an in-app channel) before an agent proceeds, then you wait for the human's response out-of-band:
const { notiflow_run_id } = await toolkit.requireHumanInput({
notiflow: "agent-approval",
recipients: [{ external_id: "ops_admin" }],
message: "Agent wants to issue a $200 refund. Approve?",
data: { amount: 200 },
});
// Wait for the response via webhook/poll on the delivery, then continue.Why it's safe to hand to an agent
- Scoped — the toolkit only exposes notiflows you allow (the
notiflowsallowlist or predicate), and only published ones. - Schema-safe — each tool advertises a JSON Schema; recipients, topic, and data are validated by the API before anything sends.
- Auditable — every trigger goes through the Management API with your account token, so it shows up in the dashboard's "Triggered by" as the token.
- Server-side only — the account token is never exposed to the model.
API surface
createNotiflowsToolkit(config)→NotiflowsToolkittoolkit.getTools({ perNotiflow?, includeGeneric? })→NotiflowTool[]toolkit.genericTool()→ thetrigger_notiflowtool (handle as an argument; supportsdraft)toolkit.listNotiflows()→ the published notiflows exposed as toolstoolkit.requireHumanInput(opts)→ trigger an approval notiflow- Adapters:
toAISDKTools,toOpenAITools,toLangChainTools
The peer dependencies ai, openai, and @langchain/core are optional and loaded lazily — install only the adapter(s) you actually use.
Related
- MCP server — manage notiflows conversationally in an editor.
- CLI — create and trigger notiflows from the terminal.
- Agent skills — teach your assistant the notiflow schemas and CLI.
- llms.txt & docs for agents — machine-readable docs for grounding an assistant.
- Notiflows for AI — the AI surfaces overview.
MCP Server
Connect the hosted Notiflows MCP server to Claude Code, Cursor, or Claude Desktop and manage, publish, and trigger notiflows conversationally over the Model Context Protocol.
Agent Skills
Install the Notiflows agent skills to teach any compatible AI assistant the notiflow and template schemas, the CLI, and where authoritative docs live — grounded in the real product.