Tools

The three-layer tool system: built-in, external, and MCP.

Tools

Nebflow gives agents three kinds of tools — built-in, external, and MCP — all exposed through the same uniform interface.

The Uniform Interface

From an agent's point of view, every tool is the same shape:

  • name — how the agent refers to it
  • input schema — the arguments it accepts
  • text result — the result, always text (Markdown, JSON, or plain)

The agent never cares which layer a tool comes from. This keeps prompts simple and lets you swap implementations without touching agent definitions.

Layer 1: Built-in Tools

Implemented in Scala, always available:

| Tool | Purpose | |------|---------| | Read | Read a file from disk | | Write | Write a file | | Edit | Targeted string replacement in a file | | Bash | Run a shell command | | Grep / Glob | Search file contents / names | | Mail | Message another agent or trigger a flow | | WebSearch / WebFetch | Access information beyond training data | | Card | Render an HTML card into the UI | | Screenshot | Capture and verify a web page |

Layer 2: External Tools

Defined as JSON + script on disk, resolved via the $TOOL_DIR variable. They wrap arbitrary executables — Python, Node, shell — into the uniform tool interface.

Resolution order (4-level scan)

$TOOL_DIR/                     # Global tools (all agents)
$TOOL_DIR/agents/<name>/       # Per-agent tools
$TOOL_DIR/teams/<team>/        # Per-team tools
$TOOL_DIR/flows/<flow>/        # Per-flow tools

More specific scopes override more general ones with the same tool name.

Structure

tools/
├── global-tools.json          # Global tool definitions
├── my-tool/
│   ├── tool.json              # name, description, input schema
│   └── run.sh                 # Executable (receives JSON args on stdin)

Layer 3: MCP Tools

Model Context Protocol servers expose tools as mcp__<server>__<tool>.

Global configuration

nebflow.json declares MCP servers globally:

{
  "mcpServers": {
    "github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"] }
  }
}

Per-agent filtering

An agent's mcpServers field is an allowlist — the agent may only call MCP tools from the listed servers:

{
  "name": "release-manager",
  "mcpServers": ["github"]
}

No mcpServers field means no MCP access at all. This is a deliberate default: MCP servers can be powerful and side-effectful, so they must be explicitly granted.

Agent-specific MCP

An agent directory can also ship its own MCP servers in a tools/ folder:

agents/my-agent/
├── agent.json
├── system.md
└── tools/mcp-servers.json     # MCP servers scoped to this agent

Tool Safety

| Rule | Why | |------|-----| | Tools are granted per-agent | Least privilege | | MCP defaults to off | Explicit consent for powerful tools | | External tools are sandboxed scripts | No arbitrary code execution | | Bash requires explicit grant | Command injection surface | | Agent output escapes HTML | XSS prevention (Card rendering) |

Best Practices

  • Grant the minimum tool set an agent needs
  • Name external tools with clear verbs (pdf-extract, deploy-site)
  • Document each tool's input schema — agents rely on it
  • Keep MCP servers shared where possible; use per-agent only for truly local needs