Core Concepts
Composable orchestration
Section titled “Composable orchestration”NimbleBrain’s core value is composing multiple MCP servers into a single, orchestrated workspace. Rather than connecting to one MCP server at a time, NimbleBrain aggregates tools from every installed app into a unified namespace, layers prompts to give the agent awareness of all available capabilities, and filters tool access per-task through skills.
┌──────────────────────────────────────────────────┐│ ToolRegistry ││ ││ ┌─────────┐ ┌─────────┐ ┌──────────────────┐ ││ │ App 1 │ │ App 2 │ │ App 3 │ ││ │ (HTTP) │ │ (HTTP) │ │ (SSE) │ ││ │ 3 tools │ │ 5 tools │ │ 2 tools │ ││ └─────────┘ └─────────┘ └──────────────────┘ ││ ││ Unified namespace: 10 app tools + system tools │└──────────────────────────────────────────────────┘ │ │ ▼ ▼ Skill filtering Agent Engine (allowed-tools) (agentic loop)Three mechanisms make this composable:
| Mechanism | What it does |
|---|---|
| Tool aggregation | The ToolRegistry collects tools from every MCP source (local stdio, remote HTTP/SSE) and presents them as a flat namespace. The agent doesn’t know or care which server owns a tool. |
| Skill-scoped filtering | Each skill declares allowed-tools glob patterns. When a skill matches, only tools matching those patterns (plus system tools) are visible to the agent. This scopes the agent’s capabilities per task. |
| 4-layer prompt composition | System prompts are assembled from: (1) identity, (2) core context, (3) installed app metadata with trust scores, and (4) the matched skill’s prompt. Every layer adds awareness without the agent needing to discover it. |
Agent loop
Section titled “Agent loop”Every chat message triggers an agentic loop in the AgentEngine. The loop repeats until the model produces a response with no tool calls, or a limit is reached.
User message │ ▼┌─────────────────┐│ Call Claude │◄─────────────────┐│ (with tools) │ │└────────┬────────┘ │ │ │ ┌────┴────┐ │ │ Tool │ Yes │ │ calls? │──────► Execute tools │ │ │ in parallel ───┘ └────┬────┘ │ No ▼ Return responseEach pass through the loop is one iteration. Defaults:
| Setting | Default | Hard cap |
|---|---|---|
| Max iterations | 25 | 50 |
| Max input tokens | 500,000 | — |
| Max output tokens | 16,384 | — |
models.default | anthropic:claude-sonnet-4-6 | — |
The engine stops for one of three reasons:
complete— the model responded without requesting any tool callsmax_iterations— the iteration limit was reachedtoken_budget— cumulative input tokens exceededmaxInputTokens. When this happens, tool calls from the current LLM response are dropped (not executed) to avoid running tools whose results can’t be processed.
All tool calls within a single iteration run in parallel via Promise.all().
Orchestration flow
Section titled “Orchestration flow”Before the engine loop starts, the Runtime orchestrates the composition described above:
- Resolve or create a conversation
- Match the user message to a skill (triggers, then keywords)
- Compose the system prompt — 4-layer: identity + core skills + installed apps + matched skill
- Filter the unified tool namespace based on the matched skill’s
allowed-toolsglobs - Run the
AgentEngineloop against the composed tool set - Persist the conversation (JSONL or in-memory)
Bundles (apps)
Section titled “Bundles (apps)”A connector is a remote MCP server a workspace connects to. The runtime orchestrates over remote MCP: it holds the server’s URL and a credential, and never downloads, verifies, or executes the server’s code. Supply-chain review belongs where the server is built and published, not in a process that also holds tenant credentials.
Sources
Section titled “Sources”Connectors are installed per workspace and tracked in workspace.json (not nimblebrain.json — entries placed there are stripped on load). They are discovered through the connectors catalog: one or more registries aggregated into a single Browse list, installed point-and-click or via manage_connectors. See Connectors Catalog.
Lifecycle states
Section titled “Lifecycle states”Each connection goes through these states:
starting ──► running ──► crashed ──► dead │ ▲ └──► stopped ─────────┘| State | Meaning |
|---|---|
starting | Connection being established |
running | Healthy and serving tools |
not_authenticated | Installed, no tokens yet — the user clicks Connect |
pending_auth | An OAuth flow is in flight |
reauth_required | Tokens were rejected — the user clicks Reconnect |
crashed | The connection dropped (will attempt recovery) |
dead | Repeatedly unreachable, not retrying on its own |
stopped | Manually stopped via API or CLI |
No connectors by default
Section titled “No connectors by default”NimbleBrain installs no connectors by default. Platform capabilities (home, conversations, files, settings, usage, automations) are built in as inline tool sources. Install connectors from the catalog to give the agent domain-specific tools.
Connector options
Section titled “Connector options”{ "url": "https://mcp.example.com/mcp", "serverName": "example"}| Field | Description |
|---|---|
serverName | The name the server registers under; tools reach the agent as <serverName>__<tool> |
transport | Transport class, auth, headers, and reconnection behavior |
ui | UI metadata: name, icon, and placement declarations |
See Connector Configuration for the full field reference.
Skills
Section titled “Skills”Skills are Markdown files with YAML frontmatter. They control what the agent knows and what tools it can use for a given message.
Skill file format
Section titled “Skill file format”---name: researchdescription: > Deep research on a topic — search the web, gather sources, and synthesize a report. Use when the user asks to research, investigate, or analyze a topic.allowed-tools: websearch__search nb__searchmetadata: nimblebrain: loading-strategy: dynamic priority: 50 triggers: - "research this" - "deep dive"---
You are a research agent. Search the web, gather multiple sources,and synthesize findings into a structured report.How a skill loads — loading-strategy
Section titled “How a skill loads — loading-strategy”loading-strategy | Priority | Behavior |
|---|---|---|
always | 0–10 (core) or 11–99 | Always composed into the system prompt — identity, voice, durable rules. |
dynamic | 11–99 | Loaded on demand, via the activation signals below. |
How dynamic skills activate
Section titled “How dynamic skills activate”A dynamic skill enters context through any of:
- Description — its name + description sit in a catalog; the model activates the relevant one (so the description must say what it does and when to use it).
- Tool-affinity — auto-activates when a tool in the active set matches one of its
tool-affinityglobs. - Triggers — auto-activates on an exact phrase, for deterministic must-fire cases.
User: "research this topic and analyze the sources" │ trigger "research this" ── match! ──► research skill activatesAn activated skill injects its markdown body into the system prompt; allowed-tools (if set) scopes which tools it may call.
Skill directories
Section titled “Skill directories”Skills are loaded from three locations (in order):
- Built-in —
src/skills/builtin/(shipped with the package) - Global —
~/.nimblebrain/skills/ - Config — directories listed in the
skillDirsconfig option
Tools come from two places: MCP bundles and built-in system tools.
System tools
Section titled “System tools”Every NimbleBrain instance has these nb__* tools available:
| Tool | Description |
|---|---|
nb__search | Search installed tools (scope: "tools") or the connector registries (scope: "registry") |
nb__status | Platform status; scope: "connectors" for per-connector health, scope: "skills" for loaded skills, scope: "config" for model and limits |
nb__read_resource | Read an MCP resource by URI |
manage_connectors | List the connector catalog, install/disconnect remote MCP connectors per workspace or per user |
manage_registries | Org-level management of the connector registries Browse pulls from |
manage_workspaces | Create and manage workspaces |
manage_members | Manage workspace membership |
manage_users | Manage users (when a managed identity adapter is configured) |
App-platform capabilities are exposed through prefixed tool families: conversations__*, files__*, automations__*, skills__*, usage__report, and compose__effective_context. (Workspace instructions are edited in the settings UI; the tool behind that UI is internal and not part of the agent’s surface.)
Tool surfacing strategy
Section titled “Tool surfacing strategy”NimbleBrain uses tiered tool surfacing to keep the LLM’s tool list manageable:
| Condition | What the LLM sees |
|---|---|
| Total tools ≤ 30 | All tools surfaced directly |
| Total tools > 30, no skill matched | Only nb__* system tools. Others available via nb__search (scope: "tools"). |
Skill matched with allowed-tools | Tools matching the globs + system tools. Others via nb__search. |
The threshold is configurable via maxDirectTools (default: 30).
Conversations
Section titled “Conversations”Conversations persist across messages so the agent remembers context.
Storage
Section titled “Storage”Conversations are workspace-owned. Every turn is written to a per-conversation JSONL file under the workspace it ran in:
~/.nimblebrain/workspaces/<wsId>/conversations/<ownerId>/<convId>.jsonlThe owner (ownerId) is the authorization principal — only they can read or resume the conversation — while the workspace (wsId) is where it is stored. Persistence is automatic; there is nothing to configure.
JSONL format
Section titled “JSONL format”Each conversation is a single .jsonl file:
{"id":"conv_abc123","createdAt":"2025-03-15T10:30:00Z"}{"role":"user","content":"What files are in my home directory?","ts":"..."}{"role":"assistant","content":"Let me check...","ts":"...","toolCalls":[...]}Line 1 is metadata (ID, creation timestamp). Lines 2+ are StoredMessage objects with role, content, timestamp, and optional tool call records.
Resuming conversations
Section titled “Resuming conversations”To continue an existing conversation, open it from the Conversations sidebar in the web UI. Through the API, pass conversationId in the chat request body.
MCP Apps
Section titled “MCP Apps”NimbleBrain is a full MCP Apps host, implementing the ext-apps specification. MCP Apps are interactive UI applications — built with HTML/JavaScript — that render directly inside the host as sandboxed iframes.
Unlike traditional web apps, MCP Apps:
- Live inside the conversation — no tab-switching, context stays together
- Call tools bidirectionally — apps invoke MCP tools and receive pushed results from the agent
- Inherit the host’s theme — CSS variables are injected automatically
- Run in a security sandbox — no access to the parent page, cookies, or other apps
Any MCP bundle that declares UI resources and placements becomes an MCP App. See MCP Apps for the full concept and MCP App Bridge for the implementation protocol.
Platform as MCP server
Section titled “Platform as MCP server”NimbleBrain exposes a /mcp endpoint that turns the platform into a Streamable HTTP MCP server. External MCP clients — Claude Code, Open WebUI, or another NimbleBrain instance — can connect through a single endpoint. Each request names its workspace via the X-Workspace-Id header (validated against your membership): /mcp serves that one workspace’s tools plus your identity tools (conversations, files, automations), and refuses tools in any other workspace. A request with no X-Workspace-Id is identity-only.
This means NimbleBrain is both an MCP client (connecting to installed bundles) and an MCP server (exposing composed tools to external hosts). See MCP Endpoint Reference for configuration and usage.