Hubzoid
Guides

Bring an existing agent

Move a Claude Code or similar agent project into a Hub file by file, or keep your assistant and connect it to a Hub through MCP.

You may already have an agent that works for you: a Claude Code project with a CLAUDE.md, a few skills, an MCP server and some scripts. There are two ways to take it to your team with Hubzoid, and they combine well.

RouteWhat happensChoose it when
Move it into a HubThe instructions, skills, sub-agents, connectors and scripts become Hub files. The agent then runs in the web chat, Slack and other channels, on schedules and in workflows, for everyone you grant access.Teammates who do not use your assistant should get the result, or the work should run unattended.
Keep your assistant, connect itThe Hub serves its tools, knowledge and skills over MCP. You and others keep using Claude Code, Cursor or another MCP client, with your own model.People already work in an assistant and want shared context and tools inside it.

The move is manual and quick for a typical project. Hubzoid has no converter, because most of the work is deciding what the shared agent should know and do.

How the pieces map

In a Claude Code projectIn a HubNotes
CLAUDE.md or .claude/CLAUDE.md (or AGENTS.md)AGENTS.mdThe body is the system prompt. Keep the parts about the work, drop the parts about the coding environment.
@path imports in CLAUDE.mdInline text, or knowledge/*.mdHubzoid does not expand imports. Reference material fits best in knowledge/.
.claude/skills/<name>/SKILL.mdskills/<name>/SKILL.mdSame file. name and description are read, other keys are ignored.
.claude/commands/<name>.mdskills/<name>.md or schedule/<name>.mdA reusable prompt becomes a skill. A prompt you run on a timer becomes a markdown task.
.claude/agents/<name>.mdagents/<name>.mdRewrite tools: as a YAML list of Hubzoid tool names, and model: as a Hubzoid model id.
.mcp.jsonconnectors/.mcp.jsonSame mcpServers map. HTTP servers need transport instead of type.
Scripts the agent runstools_local/*.pyA function decorated with @function_tool. A script that should run on a timer without the agent can be a run: task.
Data files the agent readsknowledge/ or raw_data/Short curated documents go in knowledge/. Large source material to search goes in raw_data/.
Secrets in your shell<hub>/.envSecrets for restricted tools go in restricted/.env.
Permission settings in .claude/settings.jsonrestricted/ tools and grantsWho may use a tool is decided in code and the Console, not by the model.

A worked example

An operations lead has a Claude Code project that prepares a daily report for a home goods retailer with four stores: open supplier orders, stock alerts and anything that needs escalating.

Before: ops-briefing (Claude Code)
ops-briefing/
├── CLAUDE.md
├── .mcp.json
├── .claude/
│   ├── skills/daily-reports/SKILL.md
│   ├── skills/daily-reports/template.md
│   ├── agents/supplier-research.md
│   └── commands/weekly-review.md
├── scripts/open_orders.py
├── data/orders.csv
└── docs/escalation-policy.md

After the move, the same project is a Hub:

AGENTS.md
.env
SKILL.md
template.md
weekly-review.md
supplier-research.md
escalation-policy.md
orders.py
orders.csv
.mcp.json
daily-reports.md
briefing-uses-orders.md

Create the Hub

hubzoid init ops-briefing

Run it in a new folder, outside your existing project. It writes a runnable Hub with one example of each file type and a .env with a random bridge key. Delete the examples you will not use, then copy your files in as below. See quickstart for installing Hubzoid and choosing a model.

Turn CLAUDE.md into AGENTS.md

Copy the parts of CLAUDE.md that describe the work: the goal, the rules, the tone, when to use what. Leave out build commands and coding conventions that only mattered to you in an editor. Add frontmatter for the name the team will see and a few starter prompts.

AGENTS.md
---
name: ops-briefing
description: Daily Reports and supplier follow-up for the operations lead.
suggestions:
  - Prepare today's daily report
  - Which supplier orders are late?
---

You prepare the operations lead's daily report for a home goods retailer
with four stores (north, south, east, west).

- Use the daily-reports skill for the daily briefing.
- Get open orders from the open_orders tool. Never estimate a quantity.
- Escalate according to the escalation-policy knowledge document.
- For questions about a supplier's record, use the supplier-research agent.

Replace @docs/escalation-policy.md style imports with a sentence that names the knowledge document, and move the document to knowledge/escalation-policy.md. The agent sees a menu of knowledge documents and reads one with read_knowledge when it needs it.

Move skills and commands

Copy .claude/skills/daily-reports/ to skills/daily-reports/. The SKILL.md frontmatter works unchanged. Supporting files are not loaded with the skill, so point to them by their path from the Hub root:

skills/daily-reports/SKILL.md
---
name: daily-reports
description: Build the daily report for the operations lead.
---

1. Read the layout in skills/daily-reports/template.md with read_file.
2. Call open_orders and list orders due today or overdue, by store.
3. Apply the escalation policy and put anything that needs a decision first.

A command such as .claude/commands/weekly-review.md becomes skills/weekly-review.md with name and description frontmatter. Hubzoid does not substitute $ARGUMENTS, so write the command as instructions that use whatever the person asked.

Move sub-agents

Copy .claude/agents/supplier-research.md to agents/supplier-research.md and adjust two keys:

agents/supplier-research.md
---
name: supplier-research
description: When the user asks about a supplier's delivery record or recent news.
model: claude-local/opus
tools: [web_search, http_get, read_knowledge]
---

Research the supplier with web_search and http_get and reply with a short,
sourced summary of delivery issues and news from the last 90 days.
  • tools: must be a YAML list of Hubzoid tool names. A comma-separated string such as Read, Grep stops the Hub from building, and Claude Code tool names do not exist in Hubzoid.
  • model: must be a Hubzoid model id, or be removed. Claude Code aliases such as sonnet, opus or inherit are not Hubzoid ids. A sub-agent whose model differs from the Hub's on the same engine runs on its own model as a delegate. Otherwise it is loaded into the main agent as a skill, and its tools: list is ignored.

Move MCP servers

Move .mcp.json to connectors/.mcp.json. Local (stdio) servers work as they are. For an HTTP server, replace "type": "http" with "transport": "streamable-http", because a server with a url and no transport is treated as SSE. Hubzoid expands ${NAME} but not ${NAME:-default}, so set every variable in the Hub's .env.

Before: .mcp.json
{
  "mcpServers": {
    "inventory": {
      "type": "http",
      "url": "${INVENTORY_MCP_URL:-https://mcp.example.com/mcp}",
      "headers": { "Authorization": "Bearer ${INVENTORY_TOKEN}" }
    }
  }
}
After: connectors/.mcp.json
{
  "mcpServers": {
    "inventory": {
      "transport": "streamable-http",
      "url": "${INVENTORY_MCP_URL}",
      "headers": { "Authorization": "Bearer ${INVENTORY_TOKEN}" }
    }
  }
}

In a Hub, everyone who uses the agent shares the connector's credential. If each person should act with their own account, see per-user MCP servers.

Turn scripts into tools

In Claude Code the agent ran python scripts/open_orders.py in a shell. A Hub agent has no shell, so move the logic into a tool:

tools_local/orders.py
"""Open supplier orders, moved from scripts/open_orders.py."""
from __future__ import annotations

import csv
import json
from pathlib import Path

from agents import function_tool

ORDERS = Path(__file__).resolve().parent.parent / "raw_data" / "orders.csv"


@function_tool
def open_orders(supplier: str = "") -> str:
    """Open supplier orders with their store and due date.

    Args:
        supplier: Only this supplier. Leave empty for all suppliers.

    Returns:
        JSON list of open orders.
    """
    with ORDERS.open(newline="", encoding="utf-8") as f:
        rows = [r for r in csv.DictReader(f) if r["status"] == "open"]
    if supplier:
        rows = [r for r in rows if r["supplier"].lower() == supplier.lower()]
    return json.dumps(rows)

Tool files are loaded one by one rather than as a package, so a tool cannot import a sibling file from tools_local/. Keep each tool file self-contained, or install shared code as a package. See tools and connectors.

Schedule the briefing

What you started by hand each morning can now run on its own. Scheduled tasks are Markdown files:

schedule/daily-reports.md
---
schedule: "30 7 * * 1-6"
write: ["briefings/"]
---

Prepare today's daily report with the daily-reports skill and save it
to briefings/today.md.

The task runs at 07:30 server time from Monday to Saturday with the same agent, skills and tools as chat. See markdown tasks.

Check it

Add an eval that proves the briefing uses real order data, then run the checks:

evals/briefing-uses-orders.md
---
expect_tools: [open_orders]
---
## Prompt
Prepare today's daily report.

## Criteria
Lists overdue orders by store from the tool result. Does not invent quantities.
hubzoid doctor ./ops-briefing
hubzoid test ./ops-briefing --prompt "Which supplier orders are late?"
hubzoid eval run ./ops-briefing
hubzoid run ./ops-briefing

What changes when an agent moves

  • No coding tools. On the claude-local backend, Claude Code's own tools (shell, file editing, its search and web fetch) are switched off. The agent has Hubzoid's built-in tools, such as read_file, list_files, grep_data, http_get and write_artifact, plus your own. Instructions that say "run this command" must name a tool instead.
  • Only Hub files count. Hubzoid reads AGENTS.md, not CLAUDE.md or anything under .claude/. Imports, hooks, permission settings and auto memory do not carry over.
  • Many people, one agent. In chat, each person has their own conversations and their own identity. Tools and connectors share the Hub's credentials unless you use restricted tools or per-user connections. Decide who may use what in the Console. See identity and access.
  • Checks that must always run belong in code. A rule the model is only asked to follow can be missed. Put anything that must hold every time in a tool, a restricted tool or a code workflow step.
  • Memory is explicit. Conversation history stays with each chat. Shared knowledge changes when you edit knowledge/, or when a person with the curator permission asks the agent to remember something. See memory and history.

Keep your assistant and connect it

If you and your teammates prefer to stay in Claude Code or Cursor, turn the Hub into an MCP server instead of, or as well as, moving the agent.

.env
MCP_SERVER=true

Each person creates a personal API key in the web chat and adds the Hub to their assistant:

claude mcp add --transport http ops-briefing https://hub.example.com/mcp \
  --header "Authorization: Bearer <your-api-key>"

The assistant then receives the Hub's tools (including list_skills, load_skill, list_knowledge and read_knowledge) and, when it connects, the Hub's instructions from AGENTS.md or its mcp_instructions frontmatter. Restricted tools follow the same permissions as chat, and every restricted call is audited. The MCP server leaves out the chat-only tools, delegates and the Hub's own connectors, because the assistant brings its own model and environment. The full setup is in connect an assistant.

A common pattern uses both: builders keep working in their assistant against the Hub, and everyone else uses the same Hub in chat and on schedules.

Next steps

Read this page as Markdown

Choose which cookies Hubzoid can use. You can change this at any time from Cookie settings in the footer. Read the Cookie Policy for details.