Документация доступна только на английском языке.
Agent SDK
Embed the Nib agent in TypeScript and Python programs, with in-process tools, permission callbacks, hooks, structured output and spending limits.
The Agent SDK runs the Nib agent from your own code. You send a prompt and get a stream of typed messages back. Tools you define, hooks and permission decisions run in your process; the agent itself runs in the Nib daemon, so every SDK session is an ordinary Nib session that you can open in the desktop app or resume with nib --resume.
The API is small: query() with options, a typed message stream, and your own tools, hooks and permission callbacks.
Install @nibapp/agent-sdk from npm or nib-agent-sdk from PyPI. Both need the nib CLI on your PATH, or its path in NIB_EXECUTABLE.
A first query
import { query } from "@nibapp/agent-sdk";
for await (const message of query({ prompt: "Find and fix the flaky test" })) {
if (message.type === "result") console.log(message.result, message.total_cost_usd);
}query() streams these messages:
| Message | Contains |
|---|---|
system | Session start (init) and compaction boundaries |
assistant | Text, thinking and tool-use blocks |
user | Tool results |
stream_event | Partial deltas, when includePartialMessages is on |
result | One per prompt: the final text, cost, usage, permission denials, structured output and the id of your message |
While a query runs, you can call interrupt(), setModel(), setPermissionMode() and rewindFiles() on it. Pass an async iterable of messages as the prompt to stream follow-ups.
For a back-and-forth conversation, use NibSDKClient: connect(), query(), receiveResponse(), interrupt() and disconnect(). In TypeScript it supports await using.
Approving tool calls from code
canUseTool decides any tool call that isn't already allowed by the permission mode or allowedTools. It also answers the agent's multiple-choice questions.
const run = query({
prompt: "Run the test suite and fix the first failure",
options: {
allowedTools: ["Read", "Grep", "Glob", "Bash(bun test:*)"],
canUseTool: async (toolName, input, { title }) =>
(await confirm(`Allow ${title ?? toolName}?`))
? { behavior: "allow" }
: { behavior: "deny", message: "The user declined" },
},
});canUseTool is one input to Nib's permission engine, not a way around it. Deny rules and protected paths still apply, and the sandbox still contains shell commands.
Your own tools
Define tools in your process and hand them to the agent as an in-process MCP server. The agent sees them as mcp__<server>__<tool>.
import { z } from "zod";
import { createSdkMcpServer, query, tool } from "@nibapp/agent-sdk";
const tracker = createSdkMcpServer({
name: "tracker",
tools: [
tool("get_ticket", "Look up a ticket by key", { key: z.string() }, async ({ key }) => ({
content: [{ type: "text", text: await lookUp(key) }],
})),
],
});
for await (const message of query({
prompt: "Fix TICKET-1",
options: { mcpServers: { tracker }, allowedTools: ["mcp__tracker__get_ticket"] },
})) {
if (message.type === "result") console.log(message.result);
}Hooks
hooks takes callbacks for the same events as hooks in settings (PreToolUse, PostToolUse, Stop and so on), with the same input and output JSON. In Python, register them with HookMatcher(matcher="Bash", hooks=[...]).
Options
Option names are camelCase in TypeScript and snake_case in Python (allowed_tools, permission_mode, max_budget_usd…).
| Option | Default | Meaning |
|---|---|---|
model, effort | Workspace default | provider:model or a model id, and reasoning effort |
cwd | Current directory | The workspace |
systemPrompt | Nib's full agent prompt | { type: "preset", preset: "nib", append } adds to it; a string replaces it |
permissionMode | default | acceptEdits, plan, auto, dontAsk or bypassPermissions |
allowedTools, disallowedTools | Rules such as Bash(npm test:*) or Edit(src/**) | |
canUseTool, hooks | See above | |
agents | Subagents: { name: { description, prompt, tools?, model? } } | |
mcpServers | stdio, http or sse server configs, or in-process servers | |
settingSources | All | Which of user, project and local settings, memory and MCP config load. [] loads none |
settings | Extra settings, as in settings.json | |
resume, continue, forkSession, title | Pick or fork a session | |
maxTurns | Stop after this many model turns, with error_max_turns | |
maxBudgetUsd | Stop when the query's spend reaches this, with error_max_budget_usd | |
outputFormat | { type: "json_schema", schema }; the result carries structured_output | |
includePartialMessages | false | Stream partial deltas |
abortController | Aborting stops the run | |
executable | $NIB_EXECUTABLE, then nib | The CLI to start |
daemonUrl, daemonToken | Find or start one | Connect to a specific daemon |
A program enters bypassPermissions only on its own word: it starts the query in that mode, and only such a query can switch to it later with setPermissionMode(). A person's acceptance of bypass in the terminal UI, -p or an editor doesn't open it, because an SDK program is code that someone else may have written, so it opts in in its own source.
How it works
query() starts nib -p --input-format stream-json --output-format stream-json and talks to it over standard input and output. Your in-process tools and hooks are served to the agent by the CLI on a loopback endpoint with a random port and token, and each call is forwarded to your process. Both SDKs speak the same protocol.
Behavior to know
- The default system prompt is Nib's complete agent prompt, not a minimal one.
rewindFiles(userMessageId)rewinds the conversation as well as the files. The id comes from the result'suser_message_id.
Next
- Permissions: modes and rule syntax.
- Budgets and receipts: what a run costs.
JetBrains, Zed and ACP editors
Run Nib in any editor that speaks the Agent Client Protocol — JetBrains IDEs, Zed and any other ACP client.
GitHub Action
Mention Nib on an issue or pull request, or run a prompt on a schedule, and it works on a branch, reports progress in a comment, and opens or updates a pull request.