> ## Documentation Index
> Fetch the complete documentation index at: https://ahvn.top/llms.txt
> Use this file to discover all available pages before exploring further.

# Agent Extension

> Optional agent extension persisting messages, sessions, skills, and agent recipes as workspace entities.

<Note>
  *Agent history and recipes are just rows. The agent extension stores what your runtime already produces.*
</Note>

<br />

## 1. Enable the Extension

The optional built-in `agent` extension persists agent runtime history and recipes as ordinary workspace entities. It does not replace `hb.LLM`, `LLMSession`, prompts, Toolkits, or MCP — it stores the pieces those systems already use.

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import heavenbase as hb

ws = hb.HeavenBase("agent-memory", preset="debug")
ws.enable_extension("agent")
```

The rule: the classes (`hb.Agent`, `hb.Session`, `hb.Message`, `hb.Skill`) import anywhere, but workspace rows require enablement. The class `save`/`load` helpers enable the extension on their target workspace automatically, so an explicit `enable_extension("agent")` is only needed when you want to query the rows yourself first.

<br />

## 2. Persistent Entities

The extension registers four entities:

| Entity id       | Class        | Stores                                                                                           |
| --------------- | ------------ | ------------------------------------------------------------------------------------------------ |
| `agent-message` | `hb.Message` | One OpenAI-format `payload` plus `role`, `content_text`, and `tool_call_count` query projections |
| `agent-session` | `hb.Session` | Ordered `message_ids`, `turn_count`, `tool_call_count`, runtime `state`, and aggregated `usage`  |
| `agent-skill`   | `hb.Skill`   | Parsed `SKILL.md` `frontmatter`, `skill_body`, `toolkit_refs`, and a deterministic zip `archive` |
| `agent-agent`   | `hb.Agent`   | A recipe: `llm_preset`, `prompt_ref`, `skill_refs`, `toolkit_refs`, and runtime `args`           |

The stored `Message.payload` is the canonical OpenAI-format dictionary. The projections exist for query and Catalog discovery, not as a second source of truth.

<br />

## 3. Logged CLI Runs

`hb llm chat` writes one `agent-session` row and ordered `agent-message` rows after the response completes. `hb llm session` creates one persistent session when the interactive session starts, then appends each completed user/assistant/tool iteration. The CLI output shape is unchanged.

Inspect logged history through the active workspace:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
sessions = ws.rows(hb.Session)
messages = ws.rows(hb.Message)
payloads = hb.Session.load(sessions[0]["object_id"], ws=ws).messages()
```

`Session.messages()` returns OpenAI-format payloads in session order, ready to feed back into a runtime session.

<br />

## 4. Skills

Create a Skill from a folder containing `SKILL.md`:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
skill = hb.Skill.from_path("skills/sql-analyst")
skill.save(ws=ws)
```

`SKILL.md` frontmatter may declare Toolkit refs with `toolkit:`:

```yaml theme={"theme":{"light":"github-light","dark":"github-dark"}}
---
name: sql-analyst
description: Analyze SQL-backed product data.
toolkit:
  - analytics/sql-tools:1
---
```

Skill folders are stored as deterministic zip bytes under `archive`. Use the runtime `read_skill` tool when an agent needs file contents:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
toolkit = hb.Skill.toolkit([skill], ws=ws)
text = toolkit.run("read_skill", skill_name=skill.name, path="SKILL.md")
```

<br />

## 5. Agent Recipes

An `hb.Agent` row is a recipe, not a second runtime stack:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
agent = hb.Agent(
    name="demo-agent",
    llm_preset="chat",
    prompt_ref="demo.agent.system",
    skill_refs=["sql-analyst"],
    toolkit_refs=["analytics/sql-tools:-1"],
    args={"max_steps": 8},
    ws=ws,
)
agent.save()

runtime = hb.Agent.load("demo-agent", ws=ws).build()
runtime.session.send("Use the available skills.", max_tool_turns=8)
```

`build()` resolves `hb.LLM`, `hb.Prompt`, `hb.Skill`, and registered `hb.Toolkit` refs, then returns an `AgentRuntime` whose `session` is a normal `LLMSession` with tools attached. Use `agent.new_session()` when you want a persistent `hb.Session` row for a future run.

<Note>
  The extension covers single-agent recipes today. Multi-agent orchestration is future work.
</Note>

<br />

## Further Exploration

<Tip>
  **Related resources:**

  * [Agents](/features/agents) - LLM sessions, prompts, workspace memory, and MCP tools
  * [Extensions](/features/extensions) - How entity extensions register and enable
  * [Sessions](/features/llm/sessions) - The runtime `LLMSession` that recipes build
  * [Toolkits](/features/toolkits) - Registered Toolkit refs that recipes attach
</Tip>

<br />
