Intermediate~35 minHazelJS
Design an Agent Manifest
Capture HazelJS Agent DNA: exportAgentDna, bootstrapRuntimeFromDna, CLI hazel agent run, and a reviewable YAML/JSON manifest aligned with identity, skills, policy, and SLOs.
- Authors
- editorial-team
- Published
- Last reviewed
- A clear agent goal and @Tool / Skillgate inventory
- Familiarity with budgets, approvals, and describeAgent basics
- A versioned Agent DNA / manifest as a reviewable artifact
- Use of exportAgentDna and bootstrapRuntimeFromDna / hazel agent run
- Ownership, policy, and SLO fields you can operate against
On this page
Why manifests (Agent DNA)
Prompts scattered in code reviews do not scale. In HazelJS, Agent DNA is a portable snapshot (format: hazeljs.agent.dna) of what an agent is allowed to do: identity, system prompt, model preference, tool metadata, policies, and optional contracts/SLOs. Think “deployable contract,” not documentation cosplay.
DNA is configuration + contract, not a binary of your TypeScript handlers. Tool implementations stay in @Tool code (or Skillgate handlers). DNA tells the runtime which tools exist, which need approval, and which policies/prompts to apply.
Related: /glossary/agent-dna, /glossary/agent-os, /glossary/control-plane. Docs: Agent OS, Skillgate.
Export DNA from code
import {
exportAgentDna,
serializeDna,
toMarketplacePackage,
saveMarketplacePackage,
} from '@hazeljs/agent';
import fs from 'node:fs';
const dna = exportAgentDna({
name: 'support-desk',
description: 'Support desk agent',
systemPrompt:
'Use lookupOrder for facts. Use processRefund only after lookup and approval.',
model: 'gpt-4o-mini',
tools: [
{ name: 'lookupOrder', description: 'Look up order' },
{
name: 'processRefund',
description: 'Process refund',
requiresApproval: true,
},
],
policies: [
{
id: 'refund-hitl',
tool: 'processRefund',
effect: 'require_approval',
priority: 20,
reason: 'Refunds require human approval',
},
],
contracts: [
{
name: 'support-desk-slo',
maxLatencyMs: 30_000,
fallbackAgent: 'safe-desk',
},
],
version: '1.0.0',
});
fs.writeFileSync('./dna/support-desk.dna.json', serializeDna(dna));
const pkg = toMarketplacePackage(dna, {
readme: 'Support desk agent',
keywords: ['support', 'agent-os'],
});
saveMarketplacePackage(pkg, './dna/support-desk.marketplace.json');
Manifest outline (YAML aligned with DNA)
Use YAML or JSON—keep it reviewed in PRs. Fields below mirror DNA + operating metadata you should also track:
# Reviewable manifest — maps to hazeljs.agent.dna + ops metadata
id: support-desk
version: 1.4.0
format: hazeljs.agent.dna
status: active
owners:
eng: platform-agents
product: support
identity:
name: support-desk
description: Summarize orders and gate refunds
goal: >
Answer order status from tools; never invent ids; refunds need HITL.
done:
type: structured
notes: Cite tool results; stop when answered
model: gpt-4o-mini
systemPrompt: |
Use lookupOrder for facts. processRefund only after lookup and approval.
skills: # Skillgate-curated or @Tool names
allow:
- name: lookupOrder
side_effect: read
- name: processRefund
side_effect: irreversible
requiresApproval: true
deny:
- shell
- sql_write
policy:
- id: refund-hitl
tool: processRefund
effect: require_approval
priority: 20
slos:
- name: support-desk-slo
maxLatencyMs: 30000
fallbackAgent: safe-desk
budgets:
maxSteps: 8
loopMaxIterations: 4
maxCostUsd: 0.25
memory:
layers:
working: ephemeral
session: 7d
long_term: disabled
evals:
suite: describeAgent/support-desk
gate: ci
observability:
timeline: true
inspector: true
kill_switch: feature_flag.support_desk
Bootstrap and CLI
hazel agent run uses bootstrapRuntimeFromDna—DNA + durable store + mock or OpenAI-compatible LLM:
hazel agent doctor
hazel agent run ./dna/support-desk.dna.json "Status of ORD-1001?" --mock
hazel agent runs list --dir .hazel/runs
hazel agent logs --timeline .hazel/runs/timeline.jsonl
Note: CLI DNA runs may stub tool handlers. Use your app (npm run dev / registered @Tool instances) for real tool behavior. Hot-reload (hotReloadDna / installAgentPackage) updates prompt, model, metadata, and policies on an already registered agent; new TypeScript tool bodies still require a deploy.
Design rules
- Tools are the real permissions. If it is not in DNA
tools[]/ Skillgate allow-list, it does not exist for that agent. - Budgets and SLOs are numbers (
maxSteps,loop,contract.maxLatencyMs), not paragraphs in the system prompt. - Policies are declarative (
require_approval, deny, mask)—wire the same rules intoPolicyEngineat runtime. - Evals are part of the artifact. A DNA without a
describeAgentsuite is a sketch. - Owners are mandatory. No owner, no production.
- Version bumps for tool allow-list changes, budget raises, policy changes, and model swaps.
Mapping to runtime
At deploy / sync time your app or store apply should:
- Load DNA version
- Configure tool registry / Skillgate from allowed skills
- Enforce budgets, contracts, recovery, governance on
execute - Attach eval suite id for CI and canaries
- Honor kill switch
If the runtime can ignore DNA, you have comments—not control. See Agent OS and Skillgate.
Progressive disclosure
- v1: reads only, tiny budgets, five
describeAgentcases - v2: session memory with TTL
- v3: gated write tool +
require_approval+durableSuspend - v4: SQL durable runs + worker leases
Record each step next to the DNA version.
Review checklist
- Goal and done condition clear
- Side-effect /
requiresApprovalaccurate - Deny list includes dangerous defaults (shell, unrestricted HTTP, raw SQL)
- Policies and contracts match runtime wiring
- Memory retention compatible with policy
- Eval suite exists and gates merge
- Kill switch tested
-
hazel agent run --mocksmoke passes
Anti-patterns
- Manifest that only stores the system prompt
- “Allow all tools” for convenience
- Secret values inline in DNA
- Expecting DNA to create brand-new agent classes that were never registered
- Copy-pasting DNA per environment without drift control / store lockfiles
Next
Sources
- HazelJS Agent OS guide — DNA export, hot-reload, marketplace package, CLI
- Skillgate documentation
- HazelJS Agent package