---
title: Built-in tools
description: Every tool the Hubzoid 1.0.1 runtime gives an agent, with arguments, limits, which surfaces receive it, and what the MCP server leaves out.
canonical_url: https://hubzoid.com/docs/reference/built-in-tools
last_updated: 2026-09-27
---

# Built-in tools

Every tool the Hubzoid 1.0.1 runtime gives an agent, with arguments, limits, which surfaces receive it, and what the MCP server leaves out.

Every Hub starts with the tools on this page. They are built for the Hub they run in, so file paths resolve inside the Hub folder and chat tools resolve to the current conversation. Your own tools from `tools_local/` and `restricted/`, and tools from MCP servers, are added on top.

## Summary

| Tool | What it does |
| --- | --- |
| [`read_file`](https://hubzoid.com/docs/reference/built-in-tools#read_file) | Read a text file inside the Hub folder. |
| [`list_files`](https://hubzoid.com/docs/reference/built-in-tools#list_files) | List Hub files matching a glob. |
| [`write_artifact`](https://hubzoid.com/docs/reference/built-in-tools#write_artifact) | Save a file the user can download, and return a download link. |
| [`list_artifacts`](https://hubzoid.com/docs/reference/built-in-tools#list_artifacts) | List files saved in this chat. |
| [`read_upload`](https://hubzoid.com/docs/reference/built-in-tools#read_upload) | Preview a file the user attached in this chat. |
| [`read_upload_full`](https://hubzoid.com/docs/reference/built-in-tools#read_upload_full) | Read an attached text file in full. |
| [`list_knowledge`](https://hubzoid.com/docs/reference/built-in-tools#list_knowledge) | List knowledge documents. |
| [`read_knowledge`](https://hubzoid.com/docs/reference/built-in-tools#read_knowledge) | Read one knowledge document. |
| [`list_skills`](https://hubzoid.com/docs/reference/built-in-tools#list_skills) | List skills. |
| [`load_skill`](https://hubzoid.com/docs/reference/built-in-tools#load_skill) | Load one skill's instructions. |
| [`grep_data`](https://hubzoid.com/docs/reference/built-in-tools#grep_data) | Search `raw_data/` for a pattern. |
| [`http_get`](https://hubzoid.com/docs/reference/built-in-tools#http_get) | Fetch a URL. |
| [`web_search`](https://hubzoid.com/docs/reference/built-in-tools#web_search) | Search the web. |
| [`current_time`](https://hubzoid.com/docs/reference/built-in-tools#current_time) | Current date and time in a timezone. |
| [`render_jinja`](https://hubzoid.com/docs/reference/built-in-tools#render_jinja) | Render a Jinja2 template with JSON values. |
| [`remember`](https://hubzoid.com/docs/reference/built-in-tools#remember) | Save a learning into the Hub's knowledge, for people with **Save shared knowledge** (`curator`). |
| [`call_jev`](https://hubzoid.com/docs/reference/built-in-tools#call_jev) | Typed decisions from Jev, for people with **Call Jev** (`jev`). Experimental. |
| [`my_management_scope`](https://hubzoid.com/docs/reference/built-in-tools#management-tools) | List the agents you manage and what you can grant. Optional. |
| [`propose_access_change`](https://hubzoid.com/docs/reference/built-in-tools#management-tools) | Propose a grant or removal for one person, to confirm in the Console. Optional. |
| [`propose_new_account`](https://hubzoid.com/docs/reference/built-in-tools#management-tools) | Propose a new account with access, to confirm in the Console. Optional. |
| [`connect_account`](https://hubzoid.com/docs/reference/built-in-tools#connect_account) | Send a personal link to connect an app. Optional. |
| [`run_git`](https://hubzoid.com/docs/reference/built-in-tools#run_git) | Read or sync a Git checkout. Scheduled markdown tasks only. |
| [`write_hub_file`](https://hubzoid.com/docs/reference/built-in-tools#write_hub_file) | Write inside a task's declared paths. Scheduled markdown tasks only. |
| [`publish_artifact`](https://hubzoid.com/docs/reference/built-in-tools#publish_artifact) | Publish a file the run wrote as a private artifact. Markdown tasks that opt in. |
| [`send_email`](https://hubzoid.com/docs/reference/built-in-tools#send_email) | Email the account the run acts as. Markdown tasks that opt in. |

## Where each tool is available

| Tool | Chat surfaces and `/v1` | Markdown tasks | Code workflow agent calls, evals, `hubzoid test` | MCP server |
| --- | --- | --- | --- | --- |
| File, knowledge, skill, search, web and utility tools | yes | yes | yes | yes |
| `write_artifact`, `list_artifacts`, `read_upload`, `read_upload_full` | yes | yes | yes | no |
| `remember`, `call_jev` | with the capability | with the capability | with the capability | no |
| Management tools, when turned on | for people who manage access, not in Slack | no | no | for people who manage access |
| `run_git`, `write_hub_file` | no | yes | no | no |
| `publish_artifact`, `send_email` | no | when the task opts in | no | no |
| Your `tools_local/` tools | yes | yes | yes | yes |
| Your `restricted/` tools | with the permission | with the permission | with the permission | with the permission |
| Delegates (`handover_<name>`) | yes | yes | yes | no |
| Tools from `connectors/.mcp.json` and the shared browser | yes | yes | yes | no |

Chat surfaces are the web chat, Slack, WhatsApp, Telegram and the OpenAI-compatible API. The MCP server leaves out the four chat-scoped tools because an MCP call has no conversation to save files into or read attachments from. It also leaves out `remember`, `call_jev` and delegates, and it does not relay the Hub's own MCP servers. `connect_account` is covered [below](https://hubzoid.com/docs/reference/built-in-tools#connect_account).

Markdown tasks and code workflow agent calls run without a chat, so `write_artifact` saves into `output/<session>/` and reports a local path, and the upload tools have nothing to read. Evals run each case in its own chat, `eval-<case>`.

## Files and uploads

### read\_file

Read a UTF-8 text file under the Hub folder.

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `path` | `string` | Required | Path relative to the Hub root, or an absolute path that resolves inside the Hub. |
| `offset` | `integer` | `0` | Character offset to start from. |
| `limit` | `integer` | `0` | Maximum characters to return. 0 applies the default cap. |

Without a `limit`, results over 25,000 characters are cut, and the full text is saved to an overflow file whose path the result names, so the agent can continue with `offset` and `limit`. Paths outside the Hub and anything under `restricted/` are refused.

### list\_files

List files under the Hub folder that match a glob.

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `glob` | `string` | `"**/*"` | Glob relative to the Hub root, for example knowledge/\*.md or raw\_data/orders/\*\*/\*.csv. |

Returns up to 100 paths, with a note to narrow the glob when there are more. Files under `restricted/` are never listed.

### write\_artifact

Save a text file for the user and return a download link.

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `filename` | `string` | Required | Bare file name, for example report.html. Directory parts are removed. |
| `content` | `string` | Required | UTF-8 text to write. |

The file goes to `.hubzoid/chats/<chat>/artifacts/`. The link is signed, so a browser can open it without an API key, and it is built from `HUBZOID_PUBLIC_URL`, then `WEBUI_URL`, then the bridge's loopback address. The runtime also shows the link to the user even when the model does not repeat it. Links expire only when `HUBZOID_ARTIFACT_LINK_TTL` is set. The built-in `dashboard` skill uses this tool to deliver single-file HTML dashboards. These chat downloads are separate from published artifacts, which workflows create with `hub.publish_artifact` and people open in the artifact viewer.

### list\_artifacts

List the files saved in this chat so far, with their sizes. Takes no arguments.

### read\_upload

Preview a file the user attached in this chat. The preview depends on the file type.

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `filename` | `string` | Required | Bare file name of the upload, for example spec.pdf. |
| `offset` | `integer` | `1` | Text. First line to return, counting from 1. |
| `limit` | `integer` | `200` | Text. Maximum lines to return. |
| `pages` | `string` | `"1-5"` | PDF. Page range such as 2-4 or 3, counting from 1. |

| File type | Preview |
| --- | --- |
| Text | The first 200 lines, or the whole file when it is shorter. |
| JSON | A structural summary and the start of the formatted document. |
| CSV | The header, the first 20 rows and the row count. |
| PDF | Extracted text of the first 5 pages, or the pages you ask for. |
| Image | Metadata only. With `HUBZOID_VISION` on, the model sees attached images directly. |
| Other binary | A hex preview of the first bytes. |

Text previews start with the file's path on disk, so the agent can pass the file to a tool that takes a path.

### read\_upload\_full

Read an attached text file in full, up to 500,000 characters.

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `filename` | `string` | Required | Bare file name of the upload. |

Refuses images and other binary files. Use it after `read_upload` when the preview says more is available.

## Knowledge and skills

### list\_knowledge

List every document in `knowledge/` as `name: description`. Takes no arguments.

### read\_knowledge

Return the body of one knowledge document.

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `name` | `string` | Required | The document name from its frontmatter, or its file name without .md. |

Both knowledge tools read the folder from disk on each call, so edits and documents saved with `remember` are visible immediately.

### list\_skills

List every skill as `name: description`. Takes no arguments.

### load\_skill

Return the instructions of one skill.

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `name` | `string` | Required | The skill name from its SKILL.md frontmatter. |

Skills include `skills/`, sub-agents loaded as skills, and on chat surfaces the built-in `dashboard` skill. The skill list is read when the Hub starts. See [Hub files](https://hubzoid.com/docs/reference/hub-files#skills-skills).

## Search and web

### grep\_data

Search inside the Hub for a regular expression or plain string. Uses `rg` (ripgrep) when it is installed and a Python search otherwise, with the same output.

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `pattern` | `string` | Required | Regular expression or literal text. |
| `path` | `string` | `"raw_data"` | Subpath of the Hub to search. Scope it narrowly, for example raw\_data/orders/2026. |
| `context` | `integer` | `0` | Lines of context around each match, from 0 to 5. |

Returns `path:line:content` lines grouped by file, most matches first. Limits: 100 matches in total, 30 per file, 300 characters per line and 25,000 characters per result, with notes on how to narrow the search. Folders such as `.git`, `node_modules`, `.venv`, `dist` and `build` are skipped, as are files over 5 MB in the Python search. The tool needs a `raw_data/` folder, and refuses paths outside the Hub or under `restricted/`.

### http\_get

Fetch a URL and return the status and body as text. No JavaScript runs and no credentials are sent.

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `url` | `string` | Required | Full http or https URL. |

Follows redirects, times out after 15 seconds, and cuts bodies at 50,000 characters. With `HTTP_ALLOWLIST` set, only the listed hosts and their subdomains are fetched. `HUBZOID_DISABLE_HTTP_GET=true` removes the tool.

### web\_search

Search the web through DuckDuckGo's HTML results. No API key is needed.

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `query` | `string` | Required | Search query. |
| `limit` | `integer` | `5` | Maximum results. |

Returns a list of titles, links and snippets. `HUBZOID_DISABLE_WEB_SEARCH=true` removes the tool.

## Utilities

### current\_time

Return the current date and time as ISO 8601, for example `2026-05-20T14:32:01+05:30`.

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `zone` | `string` | `"UTC"` | IANA timezone name, for example Asia/Kolkata or Europe/London. |

### render\_jinja

Render a Jinja2 template with values from a JSON object. Undefined variables are an error rather than empty text.

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `template` | `string` | Required | Jinja2 template source. |
| `context_json` | `string` | `"{}"` | JSON object with the template values. |

## Learning

### remember

Save a learning as a knowledge document. The tool tells the model to call it only when the user explicitly asks it to remember something.

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `topic` | `string` | Required | Short subject, for example billing edge cases. It becomes the document name learned/\<slug>. |
| `content` | `string` | Required | The complete current knowledge on the topic, as Markdown. It replaces the previous version. |

The document is written to `knowledge/_learned/<slug>.md` with the author and time in its frontmatter, and the previous version is kept as `<slug>.md.bak`. Content is limited to 100,000 bytes. Every person using the Hub can read the result through `read_knowledge`.

`remember` is on every Hub but works only for a caller who holds the `curator` permission, shown in the Console as **Save shared knowledge**, on a surface allowed to use restricted tools. On a Hub whose access is managed in the Console, grant it there or with `hubzoid grant <email> curator`. On a Hub with group-based access, membership of a web chat group named `curator` gives the same access. Until someone holds it, the tool is hidden and every call is refused. A Hub tool named `remember` replaces this one.

## Decisions

### call\_jev

Ask Jev, TypeSafe's decision model, typed questions about a piece of text through OpenRouter. It returns answers with probabilities instead of prose. Experimental.

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `state` | `string` | Required | The text to judge, for example a ticket or a message. JSON as text is fine. |
| `questions` | `object` | Required | Question name mapped to a question with type (noul, choice or score), instructions and, where the type needs them, criteria. Answers come back under the same names. |

| Type | Asks | Answer |
| --- | --- | --- |
| `noul` | Does it hold? | The probability of yes. Criteria are optional. |
| `choice` | Which label fits? | One of two or more labels given in `criteria`, with probabilities. |
| `score` | Where on a scale? | A score from 0 to the last of two or more levels in `criteria`, lowest first. |

`call_jev` is on every Hub but works only for a caller who holds the `jev` capability, shown in the Console as **Call Jev**, on a surface allowed to use restricted tools. Nobody holds it by default, and the Console shows "Jev key missing" until `JEV_OPENROUTER_API_KEY` is set. The tool uses only that key, never `OPENROUTER_API_KEY` or the Hub's model. Each call writes a usage row. A failure comes back as readable text. A Hub tool named `call_jev` replaces this one. Workflows use the same adapter as `hub.call_jev`. See the [workflow API](https://hubzoid.com/docs/reference/workflow-api).

## Management tools

With `HUBZOID_MANAGEMENT_TOOLS=true` on a Hub whose access is managed in the Console, the agent gets three tools that propose people and access changes. They only propose. Nothing changes until the same person opens the link the tool returns, signs in to the Console on the web and confirms the exact change.

| Tool | Arguments | What it does |
| --- | --- | --- |
| `my_management_scope` | none | Lists the agents the caller manages and the capabilities they can grant in each, with Console labels and ids. Read only. |
| `propose_access_change` | `person` (email), `hub`, optional `grant` and `revoke` lists of capability ids | Proposes granting or removing capabilities for one person in one agent. Removing `use_hub` removes all of that person's access there. |
| `propose_new_account` | `email`, `name`, `hub`, optional `grant` list | Proposes a new chat account with access to one agent. Chat access is included. The password is set on the confirmation page, never in chat. |

- The acting person is always the signed-in caller. No tool takes an actor, and no tool accepts or returns a password.
- They work on the web chat, the API, MCP, WhatsApp and Telegram. They refuse anonymous callers, scheduled work and every Slack surface, and are hidden from people who manage nothing.
- A proposal is checked against the caller's own access, can be used once, and expires after `HUBZOID_CHANGE_REQUEST_TTL` seconds (900 by default). At most 20 can wait per person. Each proposal, confirmation, rejection and expiry is recorded in the access log with its surface.

## Personal connections

### connect\_account

Start a connection journey for the caller's own account in an app, for example Gmail. Present on every runtime only when `HUBZOID_CONNECT_JOURNEY=true`.

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `app` | `string` | Required | The app to connect, for example gmail. |
| `reconnect` | `boolean` | `false` | Connect again even when already connected. |

Returns either a note that the app is already connected or a personal link to `/portal/connect/<id>`, which works only for the person who asked while signed in and expires after `HUBZOID_CONNECT_TTL` seconds. The caller needs the app's `connector_<app>` capability, and the app must be an OAuth 2.1 MCP server registered in the web chat with `OWUI_NATIVE_MCP=true`. See [tools and connectors](https://hubzoid.com/docs/guides/tools-and-connectors#per-user-mcp-servers).

## Scheduled task tools

A markdown task run receives two more tools, and two others when its frontmatter opts in. They are never available in chat.

### run\_git

Run a read or sync Git command in a checkout inside the Hub.

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `repo` | `string` | Required | Hub-relative path of the checkout, for example raw\_data/catalog. Use . for the Hub itself. |
| `args` | `string` | Required | Git arguments, for example log --oneline -20. |

Allowed verbs are `pull`, `fetch`, `log`, `diff`, `show`, `status`, `rev-parse`, `ls-files`, `branch`, `shortlog`, `describe` and the read-only forms of `remote`. Flags that could write files or run commands, such as `--output`, `--upload-pack`, `-c` and `--git-dir`, are refused. Each call times out after 300 seconds, and output is cut at 60,000 characters. Hubzoid itself commits the task's `commit:` paths after the run.

### write\_hub\_file

Create or overwrite a file inside the task's writable paths.

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `path` | `string` | Required | Hub-relative file path. |
| `content` | `string` | Required | Full new file content. |

Writable paths are the task's `commit:` and `write:` paths plus its scratch folder, `.hubzoid/schedule/<task>/`. The `schedule/` folder and any `.git/` folder are never writable, even under a broad `commit:` path. See [markdown tasks](https://hubzoid.com/docs/guides/markdown-tasks).

### publish\_artifact

Publish a file the run wrote as a private artifact owned by the account the run acts as. Offered only when the task sets `publish_artifacts: true`.

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `path` | `string` | Required | Hub-relative path of a file under the writable paths of the task, for example its scratch folder. |
| `title` | `string` | Required | A short title for the artifact. |

Returns the artifact's id and its viewer link, `/portal/artifacts/<id>`. Only the owner can open it until they share it. Files that hold secrets, such as `.env` files and databases, are refused. See the [HTTP endpoints](https://hubzoid.com/docs/reference/http-endpoints#artifact-viewer) for the viewer.

### send\_email

Email the account the run acts as, the only possible recipient, with optional links to artifacts published in the same run. Offered only when the task sets `send_email: true`.

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `subject` | `string` | Required | One-line subject. |
| `body` | `string` | Required | Plain-text message. |
| `artifact_ids` | `string[]` |  | Ids returned by publish\_artifact, to link. |

At most five emails per run. Only an accepted result means the SMTP server took the message, and even then it does not confirm delivery to the inbox. It uses the `HUBZOID_SMTP_*` settings, or writes to a preview outbox with `HUBZOID_EMAIL_DELIVERY=preview`. See [configuration](https://hubzoid.com/docs/reference/configuration#artifacts-and-email).

## Tools from other sources

- **Delegates.** A sub-agent that runs on its own model becomes a tool named `handover_<name>` on the OpenAI Agents and Codex runtimes, and a Claude subagent on `claude-local`. See [Hub files](https://hubzoid.com/docs/reference/hub-files#agent-definitions-agents).
- **MCP servers.** Each server in `connectors/.mcp.json` adds its tools. See [tools and connectors](https://hubzoid.com/docs/guides/tools-and-connectors).
- **The shared browser.** `HUBZOID_BROWSER=true` adds the Playwright tools, such as `browser_navigate`, `browser_click` and `browser_snapshot`, as an MCP server named `playwright`.
- **Personal MCP connections.** With `OWUI_NATIVE_MCP=true`, servers a person connected in the web chat are added for that person's turns on every runtime. On a Console-managed Hub each one also needs the person's `connector_<app>` capability. See [tools and connectors](https://hubzoid.com/docs/guides/tools-and-connectors#per-user-mcp-servers).

## Names on each backend

On the OpenAI Agents and Codex runtimes tools keep the names above, and tools from MCP servers keep their own names. On `claude-local`, Hubzoid's tools are served to Claude as an in-process MCP server, so the model sees `mcp__hubzoid__read_file`, external servers appear as `mcp__<server>__<tool>`, and personal servers as `mcp__owui_<name>__<tool>`. Eval checks such as `expect_tools` match the short name on every runtime. On `claude-local`, Claude Code's own tools (shell, file editing and the rest) are switched off, so the agent only has the tools on this page and the ones you add. The one exception is Claude's subagent tool, which is enabled when the Hub has delegates. On `codex-local`, Codex's own shell, file, browser and web search tools are switched off in the same way, and Hubzoid runs every tool the agent calls.

On every runtime the agent sees only the controlled tools (`restricted/` tools, `remember`, `call_jev`) the caller may use, and the management tools only when the caller manages access.

## Change the tool set

| To | Do this |
| --- | --- |
| Remove `http_get` or `web_search` | Set `HUBZOID_DISABLE_HTTP_GET=true` or `HUBZOID_DISABLE_WEB_SEARCH=true`. |
| Limit `http_get` to known hosts | Set `HTTP_ALLOWLIST=example.com,api.example.com`. |
| Replace a built-in | Add a `tools_local/` tool with the same name. |
| Require a permission for a tool | Put it in `restricted/<permission>.py`. See [restrict tools](https://hubzoid.com/docs/guides/restrict-tools). |
| Limit a delegate's tools | List them in the sub-agent's `tools:`. |

## Next steps

- [Tools and connectors](https://hubzoid.com/docs/guides/tools-and-connectors): Add Python tools, MCP servers and the shared browser.
- [Restrict tools](https://hubzoid.com/docs/guides/restrict-tools): Gate a tool behind a permission that the Console grants.
- [Connect an assistant](https://hubzoid.com/docs/guides/connect-an-assistant): Use these tools from Claude Code, Cursor and other MCP clients.
- [Configuration](https://hubzoid.com/docs/reference/configuration): Variables that change tool behaviour.
