Memory and history
How a Hubzoid Hub keeps authored knowledge, conversation history per surface, workflow state per account and learned knowledge saved by the remember tool.
"Memory" covers four different things in Hubzoid. They are stored in different places, written by different people or processes, and reach the agent in different ways. Keeping them apart is what lets a Hub share knowledge across a team without mixing one person's conversation into another's.
Shared across the Hub
Authored knowledge
knowledge/*.mdWritten by builders and reviewed in Git.
Learned knowledge
knowledge/_learned/Saved by the
remembertool when a curator asks.
Listed in the system prompt, read with read_knowledge
One conversation
Conversation history
Web chat keeps it in the chat app database, Slack in Slack, and WhatsApp and Telegram in the Hub database. API and MCP callers keep their own.
Earlier messages arrive with each turn
The agent
Answers with the Hub's knowledge and that conversation's history, never another conversation's.
One workflow
Workflow state
hub.stateWhat scheduled work has already done for the account a run acts as, in the operational database and per account task state folders.
Shared workflow state
hub.shared_stateState that is not about one person, shared by every account that runs the workflow.
Read and written by that workflow only
The workflow
Its code or task, on each run, as the run's account.
| Kind | Written by | Stored in | Shared with | Reaches the agent |
|---|---|---|---|---|
| Authored knowledge | Builders, in Git | knowledge/*.md | Everyone who uses the Hub | Menu in the system prompt, read_knowledge on demand |
| Conversation history | The conversation itself | Per surface, see below | The people in that conversation | The earlier messages arrive with each new turn |
| Workflow state | Workflow code and scheduled tasks | The operational database and task state files | That workflow or task, per account the run acts as. hub.shared_state is shared by every account. | Read and written by the workflow |
| Learned knowledge | The remember tool, when a curator asks | knowledge/_learned/*.md | Everyone who uses the Hub | Like authored knowledge |
Authored knowledge
Knowledge is the Hub's reference material: definitions, policies, thresholds and how your systems fit together. It lives in knowledge/ as Markdown, is reviewed like code, and changes when someone edits it. The system prompt lists each document's name and description, and the agent reads a document in full with read_knowledge(name) when it needs it.
read_knowledge and list_knowledge read the folder from disk on every call, so an edit is visible to the next tool call without a restart. See the Hub.
Conversation history
The bridge does not keep conversations. Each chat request carries the conversation so far, and the bridge flattens it into one prompt with [system], [user] and [assistant] sections. Where that history comes from depends on the surface:
| Surface | Where history lives | What the agent receives |
|---|---|---|
| Web chat (Open WebUI) | The chat app's database: <hub>/.openwebui-data/webui.db on a single Hub, webui.db in the gateway's data folder, or PostgreSQL when DATABASE_URL is set | The whole conversation, sent by the chat app on every turn |
| Slack | Slack itself | The thread, read back from Slack on every turn |
| WhatsApp, Telegram | The hz_inbound_history table in the Hub database (<hub>/.hubzoid/hub.db, or PostgreSQL) | The most recent messages for that chat, 40 by default |
| OpenAI-compatible API | Your application | Whatever messages list your application sends |
| MCP clients | The client application | Nothing. Each MCP tool call stands alone, and the client keeps its own conversation. |
| Generic webhooks | Not applicable | Each delivery is stored as an event file for a task to process. There is no conversation. |
History is separate per surface and per conversation. A question asked in Slack is not visible in the web chat, and one WhatsApp chat never sees another.
For WhatsApp and Telegram, Hubzoid keeps the thread itself because those platforms do not replay it. Only the visible answer is stored, without the thinking panel or tool entries. Two settings bound it:
| Key | Default | Effect |
|---|---|---|
INBOUND_HISTORY_MAX | 40 | Messages kept per chat, about 20 turns. Older messages are deleted as new ones arrive. |
INBOUND_HISTORY_TTL_DAYS | unset | When set, messages older than this many days are deleted each time the chat stores a new message. |
Usage rows in hz_usage record the time, surface, person, chat id, model, tokens, estimated cost and duration of every turn. They never contain message content.
Workflow state
Scheduled work needs to remember what it has already done. That memory belongs to the workflow and to the account a run acts as, not to a conversation. Every scheduled run acts as an ordinary account, chosen by run_as or the Hub's default, as described in workflows and schedules.
Code workflows use hub.state, a dictionary-like store in the operational database (hz_workflow_kv). Keys are scoped to the Hub, the workflow and the run's account, so two workflows never collide and the same workflow run for someone else starts empty. For state that is not about one person, hub.shared_state is shared by every account that runs the workflow. Keep personal data out of it. Values are JSON. Each assignment is committed at once and survives restarts and upgrades.
new = [b for b in breaches if not hub.state.get(f"explained:{b['service']}:{b['window_end']}")]
...
for b in new:
hub.state[f"explained:{b['service']}:{b['window_end']}"] = reportA write to hub.state is its own commit, not a checkpointed step. If a run crashes after a write and is resumed, a read-modify-write such as a counter can be applied twice. Use per-item markers like the one above, which make a repeated run skip work it already finished. The workflow API covers the details.
Markdown tasks run each round in a fresh context, with no chat history. Continuity comes from a state file the task keeps for the run's account at <hub>/.hubzoid/schedule/<task>@<person>/state.json. Hubzoid's task preamble tells the agent to read it first and update it after every unit of work, so the next round or the next scheduled run resumes from it. Each run also writes a step-by-step log to the runs/ folder beside it. See markdown tasks.
State written before 1.0.1, in hub.state or in <hub>/.hubzoid/schedule/<task>/, is kept as it was and belongs to no account. Only a legacy Hub with no account configured still uses it.
The workflow engine separately checkpoints each completed step of a run, which is what lets an interrupted run resume without repeating finished steps. That is execution state, managed by the engine, not something your code reads.
Learned knowledge
Every Hub includes a remember(topic, content) tool that saves a durable learning as a knowledge document, so a correction made in chat reaches every later conversation. It is controlled rather than automatic.
- Curator asks
- Access check
- Decision recorded
- Document written
- Readable at once
Who can trigger it
- The caller must hold the
curatorpermission in the Hub, shown as Save shared knowledge in the Console. Grant it withhubzoid grant you@example.com curator my-hubon a Hub whose access Hubzoid manages. On a Hub with group-based access, membership of an Open WebUI group namedcuratorcounts instead. - The caller must be on a surface allowed to reach restricted tools. By default, Slack, WhatsApp and Telegram callers, anonymous requests and
hubzoid testare refused.HUBZOID_RESTRICTED_SURFACESchanges the list. - The tool's description tells the model to call it only when the person explicitly asks it to remember, save or note something, and never on its own initiative.
- In a Hub where nobody holds
curator, every call is refused. A Hub tool namedrememberreplaces the built-in one. It is not offered over MCP.
Every attempt, allowed or refused, is recorded in the access log with the person, surface and reason.
Where it writes
remember writes one Markdown file per topic:
---
name: learned/billing-edge-cases
description: Learned knowledge about billing edge cases
learned_by: you@example.com
updated: '2026-09-25T09:41:07+00:00'
---
Credit notes issued after month end are booked in the month they are issued.| Rule | Behavior |
|---|---|
| File name | The topic in lowercase letters, digits and hyphens, at most 80 characters. |
| Name | learned/<slug>, so it never collides with an authored document. |
| Size | Content above 100,000 bytes is refused. Split it into narrower topics. |
| Updates | A second remember on the same topic replaces the whole document. The model is told to read the current version first and send the complete updated text, so a correction overwrites the old claim. |
| Previous version | The version before the latest write is kept beside it as <slug>.md.bak, which the knowledge loader ignores. |
| Provenance | learned_by and updated in the frontmatter record who wrote it and when. |
The document is readable through read_knowledge('learned/<slug>') and list_knowledge on the next call, for every person who uses the Hub. The knowledge menu in the chat agent's system prompt includes it after the next restart.
Review and correct it
Learned documents are ordinary files in the Hub folder, so they go through the same review as the rest of the Hub:
- Review changes.
git statusandgit diffonknowledge/_learned/show new and changed documents since the last commit. Commit what you keep. - Correct in chat. A curator asks the agent to remember the corrected fact. The document is replaced in full.
- Correct by hand. Edit or delete
knowledge/_learned/<slug>.md. The change is visible to the nextread_knowledgecall. - Undo the last write. Restore
<slug>.md.bakover the document. - Audit who used it.
hubzoid audit my-huband the Console's Activity page list eachrememberdecision with the person, surface and outcome.
Learned knowledge is shared
A remembered fact becomes part of the Hub's knowledge for everyone who uses it, on every surface. Grant curator only to people who should change what the whole team's agent believes, and review knowledge/_learned/ as you would any other change to the Hub.
Next steps
Agents and models
How Hubzoid defines the main agent and sub-agents, when a sub-agent becomes a delegate on its own model, and how runtimes and providers are chosen.
Workflows and schedules
How Hubzoid runs recurring work as markdown tasks or code workflows on one durable engine, with triggers, concurrency, retries, catch-up rules and the account each run acts as.
