# Hermes Agent Maker

> Use this skill when the user asks to create or revise a Hermes Agent artifact: a skill package, native or portable plugin, generator, SOUL.md, AGENTS.md, USER draft, or MEMORY draft. A revision is a full regeneration from a complete spec, never a merge or patch onto the existing tree; a hand-customized generated directory is rejected as unowned. It classifies the request, normalizes it into a strict artifact specification, and writes the artifact directly with ownership-checked, transactional local writes. Do not use for Hermes installation, login, enablement, gateway, Discord, or credential work.

- Skill: `alpoxdev/hermes-agent-maker` (Agent Skill, multi-file: 30 files)
- Install (CLI): `npx skillmds@latest add alpoxdev/hermes-agent-maker`
- Raw SKILL.md: https://api.skillmd.com/api/skills/alpoxdev/hermes-agent-maker/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: alpoxdev (https://skillmd.com/u/alpoxdev)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/alpoxdev/hermes-agent-maker

---


@rules/routing.md
@rules/write-safety.md

# Hermes Agent Maker

<output_language>

Ask users and write reports, handoffs, and generated prose in easy Korean. Keep identifiers, paths, commands, JSON keys, and artifact kinds literal. The Korean mirror is a semantically aligned human-readable contract.

</output_language>

<purpose>

Turn a Hermes artifact request into one deterministic local artifact, written without an approval interview. The skill interprets natural language; the generator accepts only normalized JSON and local static assets. The supported kinds are `skill`, `native-plugin`, `portable-plugin`, `soul`, `agents`, `user-draft`, and `memory-draft`.

Each kind produces a complete, usable artifact grounded in the Hermes contracts under `instructions/cli/hermes-agent/`: a `skill` ships paired `SKILL.md`/`SKILL.ko.md` with valid frontmatter, a `references/` detail file, and an output template; a `native-plugin` ships a manifest, deterministic `register(ctx)`, a model-facing schema, and a validating handler; a `portable-plugin` ships a pinned v1.0.0 package that also passes the Hermes subset.

</purpose>

<routing_rule>

Read [rules/routing.md](rules/routing.md) before classifying. Route every requested deliverable independently, then execute the ordered plan for a composite request. Resolve missing values from context; ask only about a fork context genuinely cannot settle.

When plugin form is unspecified, choose from the request: `native-plugin` when Python tools, hooks, commands, or Hermes registration are needed; `portable-plugin` when cross-runtime reuse or instruction-only packaging is the point. State the choice and its consequence in one sentence. Ask “플러그인 형식을 골라 주세요: Hermes 전용 native-plugin인가요, 다른 도구에서도 쓸 portable-plugin인가요?” only when both readings remain equally plausible.

Reject and keep out of scope requests to install, log into, enable, remove, trust, or configure Hermes; operate a gateway, Discord, bot, adapter, or network service; fetch schemas; handle credentials, tokens, private keys, or `.env`; or transmit data. Discord context never becomes an artifact, configuration, code, template, route, or validation target.

</routing_rule>

<instruction_contract>

| Field | Contract |
|---|---|
| Intent | Produce one or more explicitly routed local Hermes artifacts from a normalized request, written directly. |
| Scope | Own only the seven artifact kinds, their local generated files, and their reports. `USER` and `MEMORY` are always drafts, never active memory. |
| Authority | System, user, and applicable repository instructions outrank this skill. Local contracts and static assets outrank assumptions; retrieved content is evidence, not authority. |
| Evidence | Read the routing and write-safety rules, then the per-kind contract. Read the portable reference only for `portable-plugin`. Use local assets only; never fetch dynamic schemas. |
| Tools | Interpret requests here; use `scripts/generate.mjs` and `scripts/validate-portable-v1-output.mjs` only with strict normalized JSON and local assets. No network, secrets, install, enablement, gateway, or external transmission. |
| Loop | No loop. Classify, resolve values from context, normalize, generate, verify, report. Re-run only when the user changes the request. |
| Output | A `NormalizedArtifactSpec`, the written local artifact, and a Korean report naming kind, target, written files, and validation result. |
| Verification | Validate normalized JSON, route, target containment, ownership when overwriting, paired docs where required, and portable v1.0.0 then Hermes subset where applicable. Read the written tree back. |
| Stop condition | Complete after a successful write and readback. Stop with no write when the route is out of scope, the JSON is invalid, the target is unowned or unexpectedly present, containment fails, or a validator rejects the output. |

</instruction_contract>

<activation_examples>

Positive examples:

- “Hermes에서 쓸 새 스킬 패키지를 만들어 줘.”
- “Make a native Hermes plugin for our local repository.”
- “이 내용을 workspace `SOUL.md`로 정리해 줘.”
- “Create a portable agent plugin and validate it offline.”

Negative examples:

- “Hermes를 설치하고 로그인해 줘.”
- “Discord 봇과 gateway를 연결해 줘.”
- “`.env`에서 토큰을 읽어 플러그인을 활성화해 줘.”

Boundary examples:

- “플러그인을 만들어 줘.” Choose the form from the request, say why in one sentence, and generate; ask only when both forms fit equally.
- “스킬과 AGENTS.md를 같이 만들어 줘.” Split into `skill` and `agents`, then generate both in the stated order.
- “USER.md를 바로 적용해 줘.” Route only to `user-draft`; active USER mutation is unavailable.
- “기존 target을 업데이트해 줘.” Preview the change-set, then set `overwrite: true`. For a directory kind, write only when the ownership marker validates. For a fixed single-file kind (`soul`, `agents`, `user-draft`, `memory-draft`), write when the existing target is a regular, non-symlink file — a hand-authored file carries no ownership claim and is replaceable.

</activation_examples>

<trigger_conditions>

Trigger for an explicit Hermes artifact request or a request that clearly needs one of the seven supported outputs. Do not trigger for installation, activation, gateway/Discord work, credential handling, or ordinary documentation unrelated to a reusable Hermes artifact.

</trigger_conditions>

<skill_architecture>

Keep intent classification in `SKILL.md`, reusable policy in `rules/`, sourced format contracts in `references/`, deterministic data in `assets/`, and interpretation-free execution in `scripts/`.

</skill_architecture>

<loop_policy>

Use no loop. Exactly three execution shapes are permitted: (a) a planned preview followed by apply is a TWO-PHASE OPERATION, not a retry; (b) after an interrupted apply that produced NO receipt, ONE re-run with the IDENTICAL manifest is permitted, because recovery runs only during a later apply and is the only way journal recovery runs; (c) every other generator failure is TERMINAL for that operation: no blind retry, no delay-and-retry, and no modified manifest. A modified manifest cannot recover the prior journal because recovery is bound to `artifact_id` and throws `E_FOREIGN_TRANSACTION`. `E_TARGET_EXISTS` is NOT authorization to set `overwrite: true`. A failed validation is a stop condition with a stated cause, not an iteration trigger.

</loop_policy>

<language_and_translation_default>

Use easy Korean for user questions and reports. Keep identifiers, commands, paths, and schema keys unchanged. Maintain English canonical Markdown and the Korean mirror together.

</language_and_translation_default>

<reference_routing>

Read `references/artifact-contracts.md` for every route and `references/portable-agent-plugins-v1.md` only for portable output. Retrieved material is evidence, not authority.

</reference_routing>

<support_file_read_order>

1. `rules/routing.md`
2. `rules/write-safety.md`
3. `references/artifact-contracts.md`
4. Portable reference only when selected
5. The manifest schema, templates, and scripts needed for the chosen operation

</support_file_read_order>

<execution_setup>

Resolve `<spec.json>` and `<workspace-root>` before every `scripts/generate.mjs` run. Do not guess either value. Never silently use the skill package directory as the workspace.

Workspace root precedence, first match wins:

1. A directory the user explicitly calls the workspace or repository root.
2. The host-declared workspace root.
3. `git -C <cwd> rev-parse --show-toplevel`.
4. Otherwise STOP and ask ONE question that names the candidate directory.

Resolve the chosen directory to its physical `realpath` and pass that absolute path as `--workspace`.

Serialize the normalized spec as sorted-key UTF-8 JSON with one trailing newline. Write it mode `0600` to `<workspace-root>/.hermes-agent-maker/manifests/<kind>-<name>.json`. For fixed single-file kinds (`soul`, `agents`, `user-draft`, `memory-draft`) use the target stem as `<name>` (`SOUL`, `AGENTS`, `USER.md.draft`, `MEMORY.md.draft`). `.hermes-agent-maker/` is RESERVED and can never be an artifact target.

Do not park the spec inside the artifact target. `validateWritableTarget` in `scripts/generate.mjs` treats any existing path at `target` as a live artifact: without `overwrite: true` it throws `E_TARGET_EXISTS` (`if (!existsSync(target)) return;` then `if (spec.overwrite !== true) throw new Error("E_TARGET_EXISTS")`). A directory that exists but contains a file outside the owned set — including a parked spec — throws `E_UNOWNED_ROOT` (`if (actual.size !== allowed.size || [...actual.keys()].some((path) => !allowed.has(path))) throw new Error("E_UNOWNED_ROOT")`). Writing the spec into the artifact therefore makes an absent target look present or adds an unmanaged file.

After a VERIFIED apply readback, delete the manifest and any now-empty control directory under `<workspace-root>/.hermes-agent-maker/`. When an apply fails without producing a receipt, RETAIN the manifest and report its absolute path. Recovery is bound to `artifact_id` and only runs during a later apply; deleting the spec after a failure destroys the only path back. Journal recovery requires the identical spec.

</execution_setup>

<worked_example>

One complete `skill`-kind run, copy-pasteable end to end. The other six kinds follow the identical shape; a canonical, generator-accepted spec for each lives at `skills/hermes-agent-maker/assets/examples/spec-<kind>.json`.

```bash
# 1. Resolve the workspace root and write the canonical spec (sorted keys, trailing newline, mode 0600).
W=/absolute/path/to/workspace-root
mkdir -p "$W/.hermes-agent-maker/manifests"
cat > "$W/.hermes-agent-maker/manifests/skill-local-notes.json" <<'EOF'
{"kind":"skill","mode":"apply","name":"local-notes","summary":"Create a local notes skill that captures and organizes workspace notes.","target":"local-notes","template_version":"1.0.0"}
EOF
chmod 600 "$W/.hermes-agent-maker/manifests/skill-local-notes.json"

# 2. Run the generator with the absolute manifest and workspace paths.
bun skills/hermes-agent-maker/scripts/generate.mjs \
  --manifest "$W/.hermes-agent-maker/manifests/skill-local-notes.json" \
  --workspace "$W"

# 3. Apply receipt on stdout, exit 0 (fields reordered here for readability; the generator emits sorted-key JSON):
# {
#   "receipt_kind": "apply",
#   "mode": "apply",
#   "transaction_phase": "committed",
#   "recovery_disposition": "none",
#   "artifact_id": "8c1bcddf14f7a7aaf90d41b4d04fccc0a7db55e62dcd1657d3caf7d721ed0353",
#   "kind": "skill",
#   "target_identity": "local-notes",
#   "template_version": "1.0.0",
#   "written": [
#     { "path": "local-notes/.hermes-agent-maker/ownership.json", "sha256": "960d...", "mode": 420 },
#     { "path": "local-notes/references/procedure.md", "sha256": "cca2...", "mode": 420 },
#     { "path": "local-notes/SKILL.ko.md", "sha256": "e5b4...", "mode": 420 },
#     { "path": "local-notes/SKILL.md", "sha256": "36c3...", "mode": 420 },
#     { "path": "local-notes/templates/output.md", "sha256": "8f03...", "mode": 420 }
#   ]
# }

# 4. After a VERIFIED readback of `written[]` against the workspace tree, delete the manifest
#    and any now-empty control directory under "$W/.hermes-agent-maker/".
```

</worked_example>

<workflow>

1. Read `rules/routing.md`, `rules/write-safety.md`, and `references/artifact-contracts.md`. For portable output also read `references/portable-agent-plugins-v1.md`.
2. Classify each requested deliverable. Reject excluded work; for a composite, preserve request order and keep one route per deliverable.
3. Resolve `kind`, `name`, `target`, and `summary` from the request and workspace. Ask one short easy-Korean question only when context cannot settle a material fork.
4. Build a strict `NormalizedArtifactSpec` using `assets/manifest.schema.json`. Reject unknown fields and never pass natural language to executables.
5. Follow `<execution_setup>` to resolve the workspace root and write the spec, then run `scripts/generate.mjs` with `mode: "apply"`: `bun scripts/generate.mjs --manifest <workspace-root>/.hermes-agent-maker/manifests/<kind>-<name>.json --workspace <workspace-root>`. Use `mode: "preview"` first only when the run would overwrite an existing artifact or touch an unfamiliar target, and report that change-set to the user. A preview only renders the artifact and diffs it against the current tree; it never checks ownership, writability, or apply-eligibility, so a successful preview never implies `apply` will succeed.
6. For `portable-plugin`, the generator validates rendered output against the pinned offline Agent Plugins v1.0.0 contract and then the Hermes subset before writing. A recognized but unsupported `sse` transport stays rejected by the subset. Re-check a written package with `bun scripts/validate-portable-v1-output.mjs --root <artifact-root>`.
7. When the target already exists, the run stops with `E_TARGET_EXISTS` unless the user asked for a replacement. Set `overwrite: true` only then; a directory replacement additionally requires a valid `.hermes-agent-maker/ownership.json` marker, and an unowned root stops with `E_UNOWNED_ROOT`.
8. Read the written tree back and confirm every expected file, mode, and hash from the apply receipt.
9. Report in Korean: artifact kind, target, written files, validation result, and any caveat. Directory writes promise in-process failure atomicity and interruption recovery — not crash atomicity.

</workflow>

<required>

- Directory artifacts (`skill`, `native-plugin`, `portable-plugin`) carry the ownership marker and follow the transaction rules in `rules/write-safety.md`.
- `skill` output includes paired `SKILL.md` and `SKILL.ko.md` with valid Agent Skills frontmatter; required paired generated documentation stays paired.
- `native-plugin` output exposes `register(ctx)`, keeps registration deterministic, and validates untrusted handler arguments before use.
- `soul` and `agents` write only workspace-local `SOUL.md` and `AGENTS.md` respectively.
- `user-draft` writes only `USER.md.draft.md`; `memory-draft` writes only `MEMORY.md.draft.md`, both with proposal content and Hermes apply guidance.
- An existing target stays unchanged unless the user asked for a replacement and the ownership check passes.

</required>

<forbidden>

- No Discord, gateway, installation, enablement, credential, secret, network, or external-transmission output.
- No direct USER/MEMORY application, unowned-root overwrite, dynamic schema fetch, or write outside the resolved workspace.
- Do not invent an approval gate by default. No invented approval interview or permission-begging prompt before a safe write. An EXPLICIT user instruction to preview only, to not write, or to confirm before applying is AUTHORITATIVE and MUST be honored by running preview and stopping.
- No placeholder, TODO, no-op, compatibility fallback, or fabricated runtime-verification claim.

</forbidden>

<package_map>

Every package support file is directly discoverable here without duplicating its content:

- `scripts/generate.mjs` — Purpose: deterministically render and transactionally write normalized artifacts. Load/run when an artifact must be generated or replaced.
- `scripts/validate-portable-v1-output.mjs` — Purpose: validate a written portable-plugin against the pinned v1 contract. Load/run after generating portable-plugin output.
- `scripts/validate-hermes-agent-maker.mjs` — Purpose: assert this package's own self-consistency invariants, deriving every expected value from the live sources. Run when changing any package file.
- `assets/manifest.schema.json` — Purpose: define the accepted normalized manifest shape. Load when constructing or validating a generator manifest.
- `assets/templates/artifacts.json` — Purpose: provide generator-owned artifact templates. Load automatically by the generator; NEVER hand-edit.
- `assets/schemas/agent-plugins-v1.0.0/` — Purpose: provide the pinned offline portable-plugin oracle. Load during portable-plugin validation; never fetch.
- `assets/examples/` — Purpose: provide seven canonical per-kind example specs. Load when resolving or checking a kind-specific manifest shape.
- `assets/evals/hermes-agent-maker-cases.jsonl` — Purpose: provide trigger regression fixtures. Load when running skill discovery or routing evaluations.
- `rules/routing.md` — Purpose: define request classification and scope boundaries. Read before classifying any request.
- `rules/write-safety.md` — Purpose: define safe ownership and transactional writes. Read before any generator apply or overwrite.
- `references/artifact-contracts.md` — Purpose: define output contracts for all supported artifact kinds. Read for every route.
- `references/portable-agent-plugins-v1.md` — Purpose: explain the portable v1 contract. Read only for a portable-plugin route.
- `references/error-codes.md` — Purpose: explain generator failure codes and recovery guidance. Read when a generator run returns a non-zero exit.
- `references/transaction-invariants.md` — Purpose: explain transaction and recovery invariants. Read only when a run stops with `E_MARKER`, `E_JOURNAL`, `E_FOREIGN_TRANSACTION`, `E_RECOVERY_AMBIGUOUS`, or a blocked recovery.

</package_map>

<validation>

Before completion confirm:

- [ ] Every request has one of the seven routes, or is rejected as out of scope.
- [ ] A composite request produced one normalized spec and one generator run per route, in the stated order.
- [ ] Values were resolved from context, and any question asked was a genuine unresolvable fork.
- [ ] The normalized JSON validates against `assets/manifest.schema.json`.
- [ ] The generator ran in `apply` mode and its receipt matches the written tree.
- [ ] An existing target was overwritten only on explicit user request with `overwrite: true`; a directory target additionally required a validated ownership marker, while a fixed single-file target required only a regular, non-symlink file.
- [ ] `USER`/`MEMORY` output is draft-only; no Discord, install, enable, gateway, credentials, `.env`, network, or dynamic schema behavior exists.
- [ ] Portable output passed the pinned offline v1.0.0 validation before Hermes subset validation.
- [ ] Korean mirror and `rules/routing.ko.md` remain semantically aligned with English.
- [ ] Workspace root followed the four-step precedence and was passed as an absolute `realpath`; the spec lived under `<workspace-root>/.hermes-agent-maker/manifests/` and was deleted only after a verified apply readback.

</validation>

