---
title: "The brain in detail: build your first hub with Hubzoid"
description: How do you build an AI agent’s brain from files you can read and edit? Learn how to create a Hubzoid hub, add knowledge, skills and tools, and ask your first question.
canonical_url: https://hubzoid.com/academy/inside-ai-agents/05-the-brain-in-detail
last_updated: 2026-10-14
---

# The brain in detail: build your first hub with Hubzoid

Create a hub, add your files and ask your first question.

Lesson 5 of 9. Video length 3:22.

[Watch the video on YouTube](https://www.youtube.com/watch?v=3GcDDkrEg3c)

## Before you start

- Python 3.11 or 3.12, a virtual environment and a configured model. A provider API key may incur charges.

## Install Hubzoid

```bash title="Terminal"
mkdir hubzoid-academy && cd hubzoid-academy
python3.12 -m venv .venv
source .venv/bin/activate
pip install hubzoid
```

Run every command below from `hubzoid-academy/`, with the virtual environment active.

## Get the Wren & Page hub

This is the finished hub from the video. Download the sample code (the button above), then:

```bash title="Terminal, in hubzoid-academy/"
unzip ~/Downloads/wren-page-complete.zip
cd wren-page-complete
cp wren-page/.env.example wren-page/.env
python -c "import secrets; print(secrets.token_urlsafe(32))"
```

Open `wren-page/.env` and set `BRIDGE_API_KEYS` to the value it printed. To build your own hub instead, see [Try it](https://hubzoid.com/academy/inside-ai-agents/05-the-brain-in-detail#try-it-build-your-own-hub).

## Walk the folder

The complete Wren & Page hub:

```text
wren-page/
  AGENTS.md
  knowledge/
  skills/
  tools_local/
  raw_data/
  connectors/
  restricted/
  workflows/
  schedule/
  .env
```

```md title="AGENTS.md"
---
name: Wren & Page
description: The Wren & Page shop assistant.
suggestions:
  - How did each branch do yesterday?
  - Is anything running low at Riverside?
  - What's our returns policy?
---
You help the team at Wren & Page, an independent bookshop
with four branches: Riverside, Old Town, Station Road and Harbour.

- Answer from the shop's knowledge and tools, not from memory.
- Say which file each answer came from.
- Keep answers short: the number first, then one line of context.
- If something is unclear, ask before you guess.
- This is sample data that ends on 26 September 2026. Treat that day as yesterday.
```

## Your skill and your tool

A skill from lesson 2 goes into `skills/` as it is. A tool from lesson 3 goes into `tools_local/` with two added lines:

```py title="tools_local/check_stock.py"
import csv
from pathlib import Path
from agents import function_tool

STOCK = Path(__file__).parent.parent / "raw_data" / "stock.csv"

@function_tool
def check_stock(title: str, branch: str) -> dict:
    """Copies on hand for one title at one branch."""
    for row in csv.DictReader(STOCK.open()):
        if row["title"] == title and row["branch"] == branch:
            return {"copies": int(row["copies"]), "counted_at": row["counted_at"]}
    return {"error": "No stock record for that title and branch."}
```

The hub finds every decorated function in `tools_local/` when it starts.

## Your model: one line in .env

```bash title="wren-page/.env"
# Your own Claude Code login and plan. No API key.
MODEL=claude-local

# Or your own Codex login
# MODEL=codex-local

# For a team, use an API key instead
# ANTHROPIC_API_KEY=sk-ant-...
# MODEL=anthropic/claude-sonnet-4-6
# OPENAI_API_KEY=sk-...
# MODEL=openai/gpt-4o-mini
# OPENROUTER_API_KEY=sk-or-...
# MODEL=openrouter/anthropic/claude-haiku-4.5
```

> **Warning: Your plan is for you**
>
> `claude-local` and `codex-local` use your own subscription. A team hub runs on an API key.

## Check it, run it, ask

```bash title="Terminal, in hubzoid-academy/wren-page-complete/"
hubzoid doctor wren-page
```

```text title="What you should see (abridged)"
✓ AGENTS.md present (hub.agents_md)
✓ .env present (hub.env)
✓ Agent builds: 'Wren & Page' via ClaudeRuntime (runtime.build)
✓ 1 workflow(s) (workflows.definitions)
· 1 restricted tool(s) (access.restricted)
· hubzoid <version> (deps.versions)
✓ SQLite 3.53.4 (deps.sqlite)
✓ 1 bridge key(s) set (auth.bridge_keys)
· Sign-in is off: local mode, whoever opens the web app is the hub's owner (admin@localhost). Fine on this machine. (auth.chat_signin)
· Chat UI: Hubzoid web app (ui.mode)
✓ Local mode: the web app stays on 127.0.0.1 (exposure.local_mode)
· No deployment key yet; one is created in …/wren-page/.hubzoid/secret.key when first needed. Back it up apart from the data. (deployment.key)
✓ The public port listens on 127.0.0.1; bridges stay on 127.0.0.1 (exposure.bind)
· claude-local: uses the local `claude` login (check it with `claude /status`) (model.credentials)
```

```bash title="Terminal, in hubzoid-academy/wren-page-complete/"
hubzoid run wren-page
```

```text title="What you should see (abridged)"
✓ Hubzoid is ready: http://127.0.0.1:3080  (local mode, sign-in off)
  Connect Claude Code: claude mcp add --transport http wren-page http://127.0.0.1:3080/mcp
```

The first start can take a little while. When it is ready, Hubzoid opens the web app in your browser. If it doesn't, open [127.0.0.1:3080](http://127.0.0.1:3080). The chat is the Hubzoid web app, so it looks different from the video. Ask "What's our returns policy?" Expect a `read_knowledge` step, then refunds within 30 days, store credit up to 45 days, and `returns-policy` as the source.

## Add a restricted tool

The invoice check reads purchase prices and agreed discounts, so it goes in `restricted/`. The file name is the permission: `check_invoice`.

```py title="restricted/check_invoice.py (opening lines)"
"""Check a publisher invoice against its purchase order.

Restricted: it reads purchase prices and agreed discounts, so it lives in
restricted/. The file name is the permission: check_invoice. Until someone is
granted check_invoice, the brain won't run it for them.
"""
from agents import function_tool

@function_tool
def check_invoice(invoice_id: str) -> dict:
    """Compare one publisher invoice with its purchase order, line by line, including agreed discounts."""
    ...
```

```bash title="restricted/.env.example"
# Secrets for restricted tools. Copy to restricted/.env and fill in.
# The agent's own file tools cannot open anything in restricted/.
SALES_DB_URL=postgresql://user:password@db.internal/wrenandpage
```

Until someone is granted `check_invoice`, their agent doesn't see it. Lesson 9 grants it to Maya.

## Try it: build your own hub

```bash title="Terminal, in hubzoid-academy/"
hubzoid init my-hub --template minimal --model claude-local
```

```text title="What you should see (abridged)"
Initialized hub at ~/hubzoid-academy/my-hub
  wrote 20 hub files
```

The minimal starter has one small example of each file, such as `skills/hello.md` and `tools_local/hello.py`, and its `.env` is ready to use. Without `--template minimal`, `hubzoid init` creates a larger sample: an operations assistant for a fictional shop.

1. **Add your files:** your skill in `my-hub/skills/`, one knowledge file in `my-hub/knowledge/`, and your tool in `my-hub/tools_local/`, with the import and the decorator. If the tool reads a CSV, put it in `my-hub/raw_data/`.
2. **Run `hubzoid doctor my-hub`.** It should show `✓ Agent builds: 'my-hub'`. Fix anything marked `✗`.
3. **Run `hubzoid run my-hub`** and ask a question only your files can answer. Stop the Wren & Page hub first, since both use ports 3080 and 8000.

## If you're stuck

### hubzoid: command not found

Activate the virtual environment: `source .venv/bin/activate`.

### The chat opens but there is no reply

With `claude-local`, Claude Code must be installed and signed in (`claude /status`). With an API key, check the key and `MODEL` in `.env`, then restart.

### My tool doesn't appear

Check it's in `tools_local/`, with the import and the decorator directly above the function. Run `hubzoid doctor`, then restart.

### The answer doesn't say where it came from

That behaviour comes from `AGENTS.md`. Add a rule such as "Say which file each answer came from."

### Public port 3080 is unavailable on 127.0.0.1

Something else uses the port. Start on another one with `hubzoid run wren-page --port 3090`. If the message names the bridge port 8000, another hub is probably running: stop it, or add `--bridge-port 8010`.

### Workflows fail on Python 3.12

On Python 3.12 the workflow engine needs SQLite 3.42 or newer. `hubzoid doctor` shows it as `deps.sqlite`.

## Go deeper

- [Quickstart](https://hubzoid.com/docs/getting-started/quickstart): Install, create a hub and ask a first question.
- [Project structure](https://hubzoid.com/docs/getting-started/project-structure): Every folder in a hub, and what it holds.
- [Restrict tools](https://hubzoid.com/docs/guides/restrict-tools): Put a tool behind a named permission.
- [Configuration](https://hubzoid.com/docs/reference/configuration): Every setting you can put in .env.
- [hubzoid doctor](https://hubzoid.com/docs/reference/doctor): What each check means, and how to fix it.
- [Agents and models](https://hubzoid.com/docs/concepts/agents-and-models): Choose a runtime and a model.

## Transcript

### Intro (0:00)

Welcome to part two of Inside AI Agents. Now we get hands on. This time, the brain itself, file by file.

### Build it on a laptop first (0:09)

Maya is setting up the shop's brain. She starts on her own laptop, so she can see every piece, and try it before the team does.

### Install, and create a hub (0:18)

You'll need Python, and Claude Code or Codex, logged in. Hubzoid is a Python package. Maya installs it, then creates a hub called wren-page. And there it is. The brain is a folder.

### Walk the folder (0:31)

The new hub comes with small examples. Maya swaps them for the shop's own files.

AGENTS.md holds the main instructions. Who the agent is, and how it should work.

Knowledge holds what's true. The returns policy, the KPI definitions, and more. Each is a markdown file. At the top, a name and a one-line description. That's the menu the model reads. Below it, the policy itself, in plain words.

Skills holds how the work is done. The same kind of header, then the steps.

Raw data holds bigger files, like the stock sheet. And connectors is where MCP servers go, when the brain needs one.

### Your skill and your tool (1:14)

Remember the skills and tools from part one? Here's where yours go. A skill goes in skills. A tool goes in tools_local. Import function tool, and put it above the function. The hub finds it when it starts.

Here, it reads the stock sheet.

### Your model (1:31)

The model is one line in the .env file. Maya chose claude-local. It runs through Claude Code on her laptop, on her own Pro or Max plan. No API key needed. codex-local works the same way. But her plan is for her. When the team uses the brain, it runs on an API key, from Anthropic, OpenAI or OpenRouter.

### Run it, and ask (1:55)

Now start it. Hubzoid run, wren-page. Open the chat in your browser, and ask something only your files can answer. What's our returns policy? Refunds within thirty days, store credit up to forty-five, and it names the file it came from.

### Add a restricted tool (2:13)

Now Maya adds one more tool. The invoice check. It looks up each order in the shop's sales database, and compares it with the publisher's invoice, prices and discounts included. Only a few people should use it.

So it goes in a folder called restricted. The file name becomes the permission. Check invoice. Its secrets, like the database password, go in restricted/.env, which the agent's own file tools can't open. Until someone is granted check invoice, the brain won't run it for them. We'll grant it to Maya later in the series.

### A folder you own (2:50)

So that's the brain, in detail. A folder you own, in plain files. A model you choose. And sensitive tools behind a permission.

### Try it and next (2:59)

Try this. Install Hubzoid, and create a hub. Drop in your skill and your tool. Run it, and ask something only your files can answer. Every file from this video is on the website. The link is in the description.

Next time, the team moves in. Sam gets an account, and starts asking in chat.

## What the video shows

- The example hub includes AGENTS.md, knowledge, skills, tools_local, raw_data, connectors and restricted files.
- Restricted prices and discounts stay outside generally readable knowledge.

## Files and further reading

- [Download Hub instructions](https://hubzoid.com/academy/examples/wren-page/AGENTS.md)
- [Download Stock tool](https://hubzoid.com/academy/examples/wren-page/tools_local/check_stock.py)
- [Download Complete example ZIP](https://hubzoid.com/academy/examples/wren-page-complete.zip)
- [Quickstart](https://hubzoid.com/docs/getting-started/quickstart)
- [Hub file reference](https://hubzoid.com/docs/reference/hub-files)
