Prompt utilities treat prompt text as structured runtime data, not as scattered f-strings.
This page starts with lightweight string builders, then shows how those builders connect to fast_prompt_section(...), hb.Prompt, workspace rows, translations, and the prompt CLI.
1. Core Idea
LLM applications spend a lot of time assembling context: task descriptions, examples, input schemas, instructions, and the new instance to solve. If every call site formats that text by hand, prompts drift and become hard to test.
HeavenBase splits prompt work into three levels:
- String and Markdown helpers create stable text blocks.
fast_prompt_section(...) turns common agent sections into OpenAI-style messages.
Prompt stores callable prompts and template prompts as workspace rows, with optional translations.
hb.Prompt turns a prompt into a callable Python object and a HeavenBase entity. Function prompts are captured through Capsule manifests and stored as sys-prompt rows. Translation entries live as queryable sys-translation rows in the same workspace, and most code should reach them through prompt.tr.
2. Build Readable Prompt Text
Use string helpers when you need Markdown that stays stable across generated prompts, reports, and tests.
from heavenbase.utils import bullet_list, code_block, md_section
content = md_section(
title="Task",
content="Inspect the workspace and report the next action.",
sections=[
{"title": "Rules", "content": bullet_list(["Read files first", "Use HeavenBase utilities"])},
{"title": "Example", "content": code_block("result = hb.HeavenBase.load('demo')", lang="python")},
],
)
Use json_block(...), file_block(...), example_block(...), bullet_dict(...), and numbered_list(...) when prompt text needs structured examples rather than hand-built strings.
3. Assemble Agent Messages
Use fast_prompt_section(...) when a common agent prompt needs descriptions, examples, instructions, and a new input instance.
import heavenbase as hb
messages = hb.fast_prompt_section(
system="You are a task agent using HeavenBase as memory.",
descriptions={"Context": ["Workspace: docs-demo", "Mode: dry-run"]},
instructions=[
"Inspect relevant files before running commands.",
"Return one concise status update.",
],
)
user_message = messages[-1]["content"]
Pass separate_system=True when the target LLM path should receive a dedicated system message instead of one user message containing all sections.
4. Function Prompts
Decorate a Python function when the prompt logic should stay in code and persist as a Capsule-backed callable.
import heavenbase as hb
@hb.Prompt(name="demo.greet")
def greet(name: str, *, tr=str) -> str:
return f"{tr('Hello')}, {name}!"
greet.register()
greet.tr.set("Hello", "zz", "HEY")
assert greet("Ada", lang="zz") == "HEY, Ada!"
assert hb.Prompt.load("demo.greet", lang="zz")("Bob") == "HEY, Bob!"
Construction does not write to a workspace. Call prompt.register(...) explicitly, or pass register=True when you intentionally want decorator-time registration. For agent workflows, pass ws=... on register and load so prompt versions and translations stay scoped to the task workspace.
5. Template Prompts
Passing a string to hb.Prompt(...) creates a format-string prompt that is compiled into the same Capsule-backed callable form as function prompts. The whole template can be translated, and selected placeholder values can be translated before formatting.
import heavenbase as hb
welcome = hb.Prompt(
"Hello, {name}! Welcome to {place}",
name="demo.welcome",
tr_keys=["place"],
)
welcome.register()
welcome.tr.set("Hello, {name}! Welcome to {place}", "zz", "HEY, {name}! GO {place}")
welcome.tr.set("Tokyo", "zz", "TOKIO")
assert welcome(name="Ada", place="Tokyo", lang="zz") == "HEY, Ada! GO TOKIO"
Use a short template without tr_keys when only the full string needs translation:
import heavenbase as hb
welcome = hb.Prompt("Hello, {name}", name="demo.welcome")
text = welcome(name="Ada")
6. Load, List, and Version Prompts
Prompts are loaded by dotted name, compact version ref, or row id:
import heavenbase as hb
hb.Prompt.load("demo.greet")
hb.Prompt.load("demo.greet:2")
hb.Prompt.list(prefix="demo.")
hb.Prompt.versions("demo.greet")
hb.Prompt.delete("demo.greet:2")
Latest-version selection considers active rows only. Tombstoned rows are hidden from default loads and lists.
Register in a workspace when you want the prompt stored as a sys-prompt row:
import heavenbase as hb
ws = hb.HeavenBase("prompt-docs", preset="debug")
welcome = hb.Prompt("Hello, {name}", name="demo.welcome", ws=ws)
welcome.register(ws=ws)
loaded = hb.Prompt.load("demo.welcome", ws=ws)
Prompt rows can restore executable Capsule manifests. Load persisted prompts only from workspaces you trust.
7. Translate Prompt Text
Each prompt binds its own translation dictionary by default. Additional dictionaries can be bound in fallback order.
prompt.tr.bind("shared.agent-ui")
prompt.tr.set("Hello", "zz", "HEY", dict_name="shared.agent-ui")
prompt.tr.unbind("shared.agent-ui")
prompt.tr is the translation helper bound to the prompt, while stored rows remain regular sys-translation rows and can be queried like other HeavenBase entities.
Translation is exported from heavenbase.prompt for lower-level code, but the root import heavenbase as hb surface keeps translation under Prompt.tr.
Lookup checks exact rows first, then source patterns with {placeholder} captures. If no translation is found, HeavenBase returns the source text for elicit="none". elicit="llm" is reserved and raises NotImplementedError in this release.
Prompt calls resolve language in this order: explicit lang=..., the prompt object’s bound lang, the current CM_HVNB config scope at heavenbase.prompt.lang, then main_lang.
import heavenbase as hb
ws = hb.HeavenBase("prompt-tr-docs", preset="debug")
prompt = hb.Prompt("Hello, {name}", name="demo.hello", ws=ws)
prompt.tr.set("Hello, {name}", "zz", "HEY, {name}")
assert prompt(name="Ada", lang="zz") == "HEY, Ada"
hb.CM_HVNB.set("heavenbase.prompt.lang", "zz", scope="heavenbase.demo-zz")
with hb.CM_HVNB.scoped("demo-zz"):
assert prompt(name="Ada") == "HEY, Ada"
8. Register Agent Instructions
Combine fast_prompt_section(...) with hb.Prompt when agent instructions should persist with the task workspace.
import heavenbase as hb
ws = hb.HeavenBase("agent-prompts", preset="debug")
def agent_bootstrap(task_dir: str, workspace_id: str, *, tr=str) -> str:
messages = hb.fast_prompt_section(
system=tr("You are a task agent using HeavenBase as memory."),
descriptions={"Context": [f"Workspace: {workspace_id}", f"Task directory: {task_dir}"]},
instructions=[
"Inspect files before running commands.",
"Write structured results to the workspace.",
"Return one plain final line.",
],
tr=tr,
)
return messages[-1]["content"]
hb.Prompt(agent_bootstrap, name="agent.bootstrap", ws=ws).register(ws=ws)
system = hb.Prompt.load("agent.bootstrap", ws=ws)(task_dir="./task", workspace_id=ws.id)
9. CLI
hb prompt list --prefix demo. --json
hb prompt show demo.greet --json
hb prompt create demo.hello --template "Hello, {name}" --tr-key name
hb prompt render demo.hello --args '{"name":"Ada"}' --lang zz
hb prompt tr-set demo.hello "Hello, {name}" zz "HEY, {name}"
hb prompt tr-list demo.hello --lang zz --json
hb prompt remove demo.hello
Function prompt creation is Python-only. The CLI create command creates template prompts.
Summary
- Use string and Markdown helpers for stable prompt text blocks.
- Use
fast_prompt_section(...) for multi-section agent messages.
- Use
hb.Prompt for callable prompts, workspace rows, versions, and translations.
- Scope register and load with
ws=... when prompts belong to a task workspace.
Further Exploration
Related resources:
- Agents - how prompts fit agent memory and MCP tools.
- Capsules - how function prompts are captured and restored.
- LLM Overview - how prompts flow into
hb.LLM.
- Configuration - prompt language defaults under
heavenbase.prompt.