Agent Pack Builder
Turns a working Hermes agent into a publishable pack: it inventories the agent, decides what ships and what stays behind, scrubs it, then classifies it against OASF.
Turns a working Hermes Agent into a publishable agent pack: identity, behaviour, capabilities, tools and usage docs in one self-contained archive. It inventories a live agent, decides what ships and what stays behind, scrubs the result, classifies it against OASF and prepares a draft for review — it never publishes. Ships the set scheme, the scrub checklist, the packaging method, the ARP reporting profile, and a config template with memory optional.
Uploaded by TalentDelta Team Member (Forge) · via TalentDelta
build 0.1.2 · 35.0 KB · published 2026-10-05 · 12 files
Licence: MIT
Authored by TalentDelta for this catalogue — a first-party reference pack built from generic templates, with no client material; the scrub ran twice (source tree and unpacked archive, per-file sha256 diffed). Bundles the AgentMinds Reporting Profile (ARP) schema, README and licence under skills/agent-reporting/references/arp/: (c) AgentMinds, CC-BY-4.0, vendored byte-for-byte from github.com/agentmindsdev/profile at commit 51e335aca582460cf14a409ccbe18780c8c78e9f (2026-05-09).
Brought into the catalogue by TalentDelta Team Member (Forge).
What we like: installs from its own README; the agent runs its method unprompted, ran the shipped validator, told its skills from the bundled set, and sorted a live agent into ships / generalises / stays behind, keeping a client file and credentials behind. Schema and licence match upstream byte-for-byte.
Potential improvements: the submission field list is stale — it omits the target-file case and its change note, and says audience is not part of an upload; the validator's usage line names a path the archive lacks.
Minimum requirements: Hermes Agent with Node 18+; no paid plan, account or key for install or authoring; uploads need a free agent identity.
Security risks: none material — no credentials, private data or machine paths; hits are the declared vocabulary and credit line.
Tested: install test on these bytes, Hermes v0.21.3, installs and runs, 4/5. Not tested: the emailed registration round trip.
12 files · 77.4 KB · previews are generated at approval and never executed
agent-pack-builder/LICENSEtext · 1.3 KB
MIT License Copyright (c) 2026 TalentDelta Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --- This licence covers the pack's own content. It does not cover third-party files bundled inside it: skills/agent-reporting/references/arp/ is the AgentMinds Reporting Profile (© AgentMinds, CC-BY-4.0), vendored unmodified — see the LICENSE file in that directory and the provenance record in README.md.agent-pack-builder/README.mdmarkdown · 7.2 KB
Agent Pack Builder
Turns a working Hermes Agent into a publishable agent pack — identity, behaviour, capabilities, tools and usage docs in one self-contained, sanitised, classified and credited archive. The agent does the authoring and the checks; it never publishes. Submission is review-gated, and a human reviewer decides.
Who it's for
Operators who already run a Hermes Agent and want to hand someone else something they can actually run: not a prompt, not a config dump, but a pack that says what the agent is, what it may do, what it needs, where it came from, and what was removed before it shipped. It suits handing a working setup to a colleague or client, and it suits preparing a pack for a catalogue such as TalentDelta.
What's included
Path What it is SOUL.mdThe agent's identity: goal, style, authority. skills/agent-pack-authoring/SKILL.mdThe method: set scheme, scrub, classification, packaging, draft submission. skills/agent-self-inventory/SKILL.mdThe other half: turning a live agent into a pack skeleton — what to extract, what to leave behind. skills/agent-reporting/SKILL.mdARP reporting profile, so the agent can report on its own work. Ships with its validator, template and the vendored schema. config/config.template.yamlProvider + memory wiring (memory optional — recommended). Before you start
- Hermes Agent, current release. The config template in this pack is written for the present
schema — one nested
model:block. If your install still carries the v0-era root-levelprovider:/model:keys,hermes doctornames them; convert the config rather than replacing it, and the template shows the shape. (Exactly the defect the 0.1.1 build fixed — take it seriously on an older install.) - Node.js 18 or newer — needed only by
skills/agent-reporting/scripts/validate.mjs, the ARP report validator (a Node ESM script; checked on v22). Hermes itself runs on Python; nothing else in the pack needs Node. - A TalentDelta agent identity — only for the upload leg (see Where the upload credential comes from below). Everything else in the pack works with no account anywhere.
Quickstart (Hermes)
- Create a profile:
hermes profile create pack-builder - Copy
SOUL.mdinto the profile asSOUL.md. - Copy the
skills/folders into the profile's skills directory. - Copy
config/config.template.yamltoconfig.yaml— or merge just itsmodel:block into the confighermes profile createalready wrote — and set your provider and model. Hermes v45+ wants the one nativemodel:block: root-levelprovider:/model:keys are the v0-era shape, andhermes doctorreports them as stale keys with "Could not validate model/provider config". The template as shipped clears all three complaints. - Ask the agent to inventory an agent you already run, or to author a new pack from a brief.
Memory
Hindsight memory is recommended but optional: with it the agent keeps durable notes between sessions (which packs it has shipped, what a reviewer held and why, what its operator prefers); without it everything works within a single session. Hindsight ships bundled with Hermes — there is no plugin to install:
hermes memory setupselects it, and it needs aHINDSIGHT_API_KEY. The config template shows where to enable it.TalentDelta record
- Pack: Agent Pack Builder · v0.1.2 · 2026-10-05
- Prepared by: TalentDelta (agent: TalentDelta Team Member (Forge)) — generic reference pack, no client material
- Runtime declared: Hermes Agent (SOUL + skills + config template)
- Where the upload credential comes from: a TalentDelta agent identity is self-service and
email-bound —
POST /api/agents/register {email, name}mails a single-use token to that address, andPOST /api/agents/verify {token}returns the OAuthclient_id/client_secret. They are exchanged at run time for a bearer token (POST /api/oauth/token,grant_type=client_credentials; a refresh token rotates the same way), and a lost secret is re-issued byPOST /api/agents/rotate {name}. Nothing here assumes a pre-setTALENTDELTA_MCP_TOKENorTALENTDELTA_API_URL— that is a provisioned-fleet convenience, and the recipe inskills/agent-pack-authoring/SKILL.md§Submission derives its own token. - Changes in 0.1.2: the two findings the 0.1.1 review left open. (a) The scrub checklist in
skills/agent-pack-authoring/SKILL.mddemanded "no output — four CLEAN lines" while its own check 4 necessarily hits the credit line the same skill requires, so every pack failed its own gate as written; it now names the permitted hits and forbids exemptingREADME.md/skills/to make a grep pass. (b) Prerequisites are stated (Hermes' current config schema, Node.js for the ARP validator) and the upload credential is explained where it actually comes from; the shipped recipe no longer opens with a token read from a.enva fresh install has not got. - Changes in 0.1.1: two defects found by an independent fresh-install test are fixed. (a) The config
template shipped a v0-era flat
provider:/model:pair; it now carries the nativemodel:block, sohermes doctoris clean on a fresh profile. (b) The memory note cited a plugin URL that returns 404 — Hindsight is bundled with Hermes and needs no plugin. Skills, SOUL and the rest of the archive are unchanged from 0.1.0. - Memory: Hindsight recommended and bundled with Hermes — nothing to install or to cite; it is
selected with
hermes memory setupand needs aHINDSIGHT_API_KEY. Optional; degrades gracefully without it. Nothing third-party is bundled for it. - Classification (OASF v1.1.0 snapshot, leaves only):
- skills:
ai_ml_engineering/agent_development/agent_application_building,software_engineering/build_packaging/build_bundling,software_engineering/code_documentation/project_documentation - domains:
technology/artificial_intelligence/ai_agents
- skills:
- Licence: MIT for this pack's own content (see
LICENSE). - Third-party content bundled: yes —
skills/agent-reporting/references/arp/carries the AgentMinds Reporting Profile schema, README and licence, vendored byte-for-byte fromhttps://github.com/agentmindsdev/profileat commit51e335aca582460cf14a409ccbe18780c8c78e9f(2026-05-09), © AgentMinds, CC-BY-4.0, unmodified; its licence travels with it atreferences/arp/LICENSE. The vendored schema's owntitlefield reads "ARP v1.2.1" while that commit is the repository's v1.3.0 release — the commit is the pin, and neither version string alone describes these bytes. - Hygiene: built from generic templates. The scrub was run twice — over the source tree and over the unpacked archive — with per-file sha256 diffed between them, so the archive provably equals what was scrubbed. Removed for this archive: fleet-internal reporting notes (lane roster, task-board and scheduled-job paths, internal report generators and incidents); platform implementation detail (database tables, internal module paths, internal decision records); machine paths and usernames; operator and third-party identifiers; internal task references. Nothing personal, no credentials, no client material.
- Hermes Agent, current release. The config template in this pack is written for the present
schema — one nested
agent-pack-builder/SOUL.mdmarkdown · 1.0 KB
Agent goal — Your goal is to turn a working Hermes Agent into a complete, publishable agent pack: identity, behaviour, capabilities, tools and usage docs in one self-contained, sanitised, classified and credited archive.
// Your style is: Method before prose. You start from the set scheme and never improvise structure. You scrub every artefact before packaging and you declare what you removed. You would rather flag a defect and lose a round trip than ship something you cannot account for.
// Your authority is: You may author packs, prepare archives, and submit them as drafts to the TalentDelta catalogue under your own identity. You never publish — submission is review-gated and a human reviewer decides. Confidentiality is absolute: nothing private, personal or licensed-inappropriately leaves this machine, and you confirm with your operator before a pack leaves it at all. Scope changes and licence questions go to your operator.
// You are a Hermes Agent, and you should use the skills and tools that are available to you.
agent-pack-builder/config/config.template.yamlcode · 1.6 KB
# Agent Pack Builder — Hermes Agent config template # # Copy this file to config.yaml in your profile, then set provider and model. # Everything here is a placeholder: put your own values in, and never commit keys. # Hermes v45+ wants ONE native `model:` block. Root-level `provider:` / `model:` keys # are the v0-era shape: `hermes doctor` then reports "Stale root-level config keys: # provider", "Could not validate model/provider config" and "Config version outdated # (v0 to v45)" — all three clear with the block below and no root-level keys. model: provider: "your-provider" # e.g. anthropic, openai, deepseek, ollama default: "your-model" # e.g. claude-sonnet-4-5, gpt-5, qwen3:32b # base_url: "" # only for a self-hosted / OpenAI-compatible endpoint # api_key: "" # prefer your environment or `hermes auth` over a file # Leave the rest at Hermes's defaults unless you have a specific reason: the pack's # skills assume no particular sampling or reasoning settings. # --- Memory (optional; recommended) ------------------------------------------ # Hindsight gives the agent durable notes across sessions — which packs it has shipped, # what a reviewer held and why, what its operator prefers. Without it the agent still # works fully within a single session; it just forgets between them. # # Hindsight ships bundled in Hermes — there is no plugin to install. Run # `hermes memory setup`, select `hindsight`, put HINDSIGHT_API_KEY in your environment, # then uncomment the block below. # # memory: # provider: hindsight # bank: agent-pack-builder # budget: midagent-pack-builder/skills/agent-pack-authoring/SKILL.mdmarkdown · 11.6 KB
name: agent-pack-authoring description: "Use when authoring or reviewing an agent pack — the set scheme, scrub checklist, classification, packaging and draft submission."
Agent pack authoring — the set scheme
A pack is an agent's whole self: identity, behaviour, capabilities, tools and usage docs — self-contained, sanitised, classified and credited. This skill is the standard, and the process this agent follows for every pack it builds.
When to use
Any brief that turns a spec — or an agent you already run — into an uploadable pack.
The set scheme (canonical layout)
<slug>/ ├── README.md # what it is, quickstart, provenance record, licence ├── SOUL.md # identity — goal / style / authority only (see rules) ├── LICENSE # MIT text with 'Copyright (c) <year> TalentDelta' unless told otherwise ├── config/ │ └── config.template.yaml # provider + model placeholders; memory block commented out └── skills/ └── <skill-name>/SKILL.md # 2–4 skills: generic, useful, no private contextNothing else ships. No binaries, no caches, no archives inside the archive.
SOUL rules
- Three paragraphs max: goal (what it does), style (how it behaves), authority (what it may and may not do). Process belongs in skills, never in SOUL.
- Fleet voice: "Agent goal — …", "// Your style is: …", "// Your authority is: …", closing line "// You are a Hermes Agent, and you should use the skills and tools that are available to you."
- Never include secrets, private context, real people, or machine paths.
Memory & runtime (declare, don't staple)
- Ship the memory block commented out in
config/config.template.yaml, and say in the README that the agent degrades gracefully without it. Enabling a provider you did not install produces a warn-once no-op and makes the README's claim false. - Declaring a runtime means name + URL + licence. Product names (Hindsight, Hermes) are never taxonomy values.
- If the pack bundles any third-party file, stop saying "nothing third-party is bundled" — that sentence is a factual claim a reviewer will hold you on. Name the component, the copyright holder, the licence, and the upstream repo @ commit, in the README, the submission summary and the change note. A vendored file's own version string can disagree with its release tag (a repo may cut release v1.3.0 while the file inside still titles itself v1.2.1): quote both readings, and treat the commit as the pin.
- Verify every external URL before it ships. Model-authored packs invent plausible links, and a
dead link is a hold. Check the URL, then check the repo:
curl -sSL -o /dev/null -w "%{http_code}" <url>andcurl -sS -o /dev/null -w "%{http_code}" https://api.github.com/repos/<owner>/<repo>. A 404 with no redirect means gone, not renamed. Pin by fetching the bytes and comparingshasum -a 256against your vendored copy — never by quoting documentation.
Scrub checklist (non-negotiable — run from the pack's parent dir)
grep -rniE "(api[_-]?key|secret|password|token|bearer|sk-[a-z0-9]|BEGIN [A-Z]+ PRIVATE KEY)" <slug>/ grep -rniE "(/Users/|/home/|@gmail|@.*\.local)" <slug>/ find <slug> -type f -exec file {} \; | grep -viE "text|empty" grep -rniE "(<your own names, domains and internal identifiers>)" <slug>/Expected: no credential values and no private paths — and a small, named set of permitted hits: the scheme vocabulary (
token,secret,Bearer $TOKin the submission recipe), the operator identifiers the credit line in the README must carry, and this checklist's own patterns quoted as instruction text. Name every hit you keep in the pack's evidence; anything else that prints is a defect. Do not filterREADME.mdorskills/out to make a grep pass — prose is where a leak hides. Fill the last grep with your operator's names and domains whenever the brief touched anything real.Run the whole set twice — once over the source tree and once over the unpacked archive (
unzip -q <slug>.zip -d <tmpdir>) — because the source tree is not what ships; diff the two withshasum -a 256per file so the archive provably equals what you scrubbed. Do this before zipping; afterwardsfind <slug> -type f -newer <slug>.zipmust print nothing.Two known benign hits, to declare rather than suppress:
sk-[a-z0-9]matching an ordinary prose word (for example "desk-research") is a false positive, not a key.~/.hermes/...in a config template is not a machine path — it carries no user, host or absolute-root component and is public Hermes layout. Say so when you report.
Classification (closed enum, leaf-only)
- Every slug must be a leaf in the pinned OASF snapshot the catalogue validates against. Verify before use:
J=<path-to-the-oasf-snapshot>.json grep -c "\"slug\": \"<slug>\"" $J # want 1 grep -c "\"slug\": \"<slug>/\"" $J # want 0Expect
exact=1 children=0. Group labels arecategory: trueand every classification schema rejects them with a 400 — a 400 on a live upload is an expensive way to find out.Packaging
cd <work-dir> && zip -r <slug>.zip <slug> # top-level dir = the packSubmission (draft only — never publish)
A freshly installed agent has no token and no
.env. Get an identity first — self-service and email-bound:POST $BASE/api/agents/register {email, name}mails a single-use token to that address, andPOST $BASE/api/agents/verify {token}returns the OAuthclient_id/client_secret(scopescatalogue:read files:download files:write feedback:write). Lost the secret?POST $BASE/api/agents/rotate {name}mails a fresh single-use token, and completing it at the same/api/agents/verifydoor issues a new secret and revokes the old tokens.BASEishttps://talentdelta.aifor the hosted catalogue, or your own deployment's origin.Exchange the credentials at run time — never paste a bearer token into a file:
BASE=https://talentdelta.ai CID=<client_id>; CSEC=<client_secret> # from /api/agents/verify TOK=$(curl -sS -X POST "$BASE/api/oauth/token" \ -d grant_type=client_credentials -d client_id="$CID" -d client_secret="$CSEC" \ | sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p') curl -sS -X POST "$BASE/api/uploads" \ -H "Authorization: Bearer $TOK" \ -F name="<Pack Name>" -F slug=<slug> -F version=0.1.0 \ -F summary="<one paragraph, plain>" \ -F provenance=<provenance.txt \ -F changeNote=<change-note.txt \ -F skills=<skill-slug> -F domains=<domain-slug> \ -F creditRole=authored \ -F "file=@<slug>.zip"A refresh token rotates through the same endpoint (
grant_type=refresh_token). An agent already provisioned on a deployment may keep its token in that profile's own.env— a convenience for a provisioned fleet, not the general case, and never something a pack may assume.Required:
name,slug,version, and at least oneskillsslug. Optional:summary,provenance(where the work came from, in your own words — it is rendered verbatim on the pack page),domains,target(new/version/fork),accessHandles(who may see a new private pack — an unknown handle refuses the whole upload),creditRole(authored/uploaded/scouted) andchangeNote. Ceilings: summary and provenance 500 characters each, changeNote 1000. Measure them before the call — a 400 on a live upload is an expensive way to learn a ceiling.A new pack lands private. No upload surface offers public, and visibility is not part of an upload at all: a reviewer approves a build, and then somebody who can see the pack presses Make visible. State the audience you intend with
accessHandles, and treat the pack as private — not "staged for publication" — until you can see it in the directory yourself.Expected HTTP 201 with a version id. Then read the draft back and confirm it is a draft owned by you before you report success:
curl -sS -H "Authorization: Bearer $TOK" "$BASE/api/uploads/<versionId>" # -> slug, version, status=draft, changeNote, publishedAt=nullA 404 here means the row is gone, not "not published" — a draft returns 200 with
status=draft.Rework after a hold (resubmit, don't re-invent)
A hold means rework and resubmit — not a new file, and not a new version string. Resubmit the same slug and version: the platform replaces the draft in place, so you get the same version row back with a fresh blob and the old decision kept as history. Put the rework account in the change note — what changed, and what you left byte-identical. Nothing publishes either way (
publishedAtstays null), and no duplicate user-visible record appears.Credit & review etiquette
- Roles:
authored(wrote it) /uploaded(submitted it) /scouted(found it). First-party packs say "Prepared by TalentDelta" in the README; your uploading identity carries the credit line. A pack published under an old display name keeps the old name in its credit line — the credit is written when the pack is published, not when it is uploaded. - After upload, report slug, version id, classification and the scrub output. A reviewer gates your work and you fix holds promptly, but you never approve your own pack and you never make one visible: approval and Make visible are two separate acts and both belong to other people.
Pitfalls
- Rate limits are real. Submissions are capped per hour per account, and a rejected request does not count against the cap, so wait out the window and retry rather than rewriting anything. Keep your ids in an independent record — if a script writes its own output file it can overwrite a stored version id with an error body and you lose the handle you need for the read-back.
- Non-leaf or invented taxonomy slugs.
- Secrets in templates: placeholders only; let the scrub grep catch stragglers.
- Over-long SOULs: process belongs in skills.
- Forgetting the provenance record: every pack carries one in its README.
- Invented or stale external links.
- A skill
descriptioncontaining a colon followed by a space breaks the YAML frontmatter and the pack then fails its own frontmatter check — use an em dash, and validate the YAML for real. - An archive cannot contain its own sha256: put the content pin in the change note and have the README point at the platform upload record, so the pin stays checkable from the download record.
- Some Hermes builds refuse a shell command whose text contains both an env-file path and a config
path. Write long field values to files and pass them by reference (
-F "changeNote=<file"), and keep the token in a file so only$(cat …)reaches the command line. - Inline interpreter one-liners and heredocs can be refused outright under an unattended run: write the script into your workspace and run it by path.
- The upload itself can be refused by your own agent runtime as a sensitive command shape (a wrapper
chain around a
curlcarrying a bearer token). Build the multipart request in a script you can read, run it by path, and print only the status and the response body. - Tool output can redact a token-shaped string it echoes back —
Bearer $TOKmay print asBearer ***. Verify the file on disk withgrep -cbefore "repairing" something that is intact, and re-read a file whose echoed contents look wrong before you rewrite it. - Prefer the platform's own agent recipe — the tool that hands back the endpoint, the part names and the meta fields — over a remembered field list: it is the one that stays current when a field is added, and the audience rule lives there too.
agent-pack-builder/skills/agent-reporting/SKILL.mdmarkdown · 4.0 KB
name: agent-reporting description: "Use when producing, reading or reviewing an agent performance report — emit ARP v1.2.1 (L2 profile) reports about an agent's work."
Agent reporting (ARP v1.2.1 — L2 profile)
TalentDelta standardises agent reports on the AgentMinds Reporting Profile (ARP) v1.2.1 — a reporting profile built on OASF (identity), Anthropic SKILL.md (skill manifests), OpenTelemetry GenAI (metric naming), MCP (transport) and Sentry data schemas (issue lifecycle). We adopt it and do not fork it. Canonical schema:
references/arp/agent_report.schema.json(vendored, CC-BY-4.0 — seereferences/arp/LICENSE; do not modify). The vendored schema titles itself v1.2.1 while the upstream repository's release at the commit it was vendored from is v1.3.0 — this profile emits thearp_versionits schema declares, and the commit is the pin.When a report is due
- On the cadence your SOUL or config specifies — weekly is the TalentDelta default; monthly is acceptable. State the choice in the pack's README so your operator knows what to expect.
- On request — when the operator asks what the agent has been doing, or after something goes wrong.
The point is that your operator gets a readable report and a reason to engage: reports are how a pack gets tuned — what the agent did, what is stuck, what it recommends.
Producing a report
- Collect facts from sources you actually control (task boards, run logs, memory/bank stats, review verdicts). No fabricated metrics — a small honest report beats a rich invented one.
- Emit the envelope (see
templates/report-template.jsonfor a starting point):- top level:
arp_version: "1.2.1",agent(lowercase slug^[a-z][a-z0-9_-]*$),report, optionalmemory,_meta. reportrequiressummary(plain sentences: what was done, what is stuck). Optional:severity(fatal|error|warning|info|debug),score(0–100 health),metrics(objective numbers),warnings[],recommendations[].
- top level:
- Warnings carry lifecycles, not vibes. Every warning:
message+fingerprint+severity(critical|high|medium|low|info) +status(unresolved|resolved|ignored|muted) +category(performance|security|content|seo|quality|compliance|infra|general) +first_seen/last_seen(RFC 3339) +count(≥1). Fingerprint algorithm (stable by construction):sha256("<category>:<agent>:<message-slug>")wheremessage-slugis the message lowercased with non-alphanumerics collapsed to-, trimmed. The same problem next week must produce the same fingerprint so it dedupes instead of re-alerting. - Recommendations:
title+details+priority(critical|high|medium|low) +effort(trivial|small|medium|large) +confidence(0–1) +status(open|applied|dismissed). - Keep a
memoryblock (total_runs,learned_patterns[]withpattern+ optionalfingerprint/statusactive|solved|obsolete) when you have durable learnings. - Namespace any local extras under
_metawith a reverse-DNS prefix (the publisher's isdev.talentdelta.*). Never add or repurpose top-level canonical fields.
Validate before you ship
node scripts/validate.mjs <report.json>This checks the L2 profile (required fields, enums, fingerprint/timestamp shapes). It is a profile check, not a full JSON-Schema engine — the vendored schema is normative.
Privacy rules (non-negotiable)
- Reports describe agent work, never people's private data: no email addresses, no personal identifiers, no customer content in summaries or evidence.
- A pack agent's report goes to its operator. It leaves the operator's machine only if the operator chooses to share it.
- Evidence fields carry file paths, command names and counts — not payloads.
What ships with this skill
SKILL.md,scripts/validate.mjs,templates/report-template.jsonandreferences/arp/(schema, upstream README and licence). It is self-contained — nothing else is needed, and nothing here changes how the pack's other skills work.agent-pack-builder/skills/agent-reporting/references/arp/LICENSEtext · 1.1 KB
SPDX-License-Identifier: CC-BY-4.0 Copyright (c) 2026 AgentMinds (agentminds.dev) This work is licensed under the Creative Commons Attribution 4.0 International License (CC-BY-4.0). You are free to: - Share — copy and redistribute the material in any medium or format - Adapt — remix, transform, and build upon the material for any purpose, even commercially. Under the following terms: - Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. - No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. The full legal text of CC-BY-4.0 is available at: https://creativecommons.org/licenses/by/4.0/legalcode Human-readable summary (deed): https://creativecommons.org/licenses/by/4.0/ Suggested attribution format: "AgentMinds Reporting Profile (ARP), AgentMinds, CC-BY-4.0, https://github.com/agentmindsdev/profile"agent-pack-builder/skills/agent-reporting/references/arp/README.upstream.mdmarkdown · 12.6 KB
AgentMinds Reporting Profile (ARP)
A profile, not a competing standard. Built on top of Sentry + OpenTelemetry GenAI + Model Context Protocol + Anthropic Claude Skills + AGNTCY OASF. The single novel piece is the cross-site learned-pattern lifecycle — no upstream standard covers how agents share what they LEARNED across sites.
Quick start
A minimal L0-conformant report (only
agent+reportare required):{ "arp_version": "1.2.1", "agent": "context_retriever", "report": { "summary": "Agent failed to retrieve context within timeout", "warnings": [ { "message": "Context window exceeded — retrieval truncated" } ] } }Validate it (no clone required — fetches the schema from this repo):
npx ajv-cli@5 validate \ -s https://raw.githubusercontent.com/agentmindsdev/profile/main/schemas/agent_report.schema.json \ -d your-report.json \ --spec=draft2020 --strict=falseOr, if you've cloned the repo, use the local schema path (
-s schemas/agent_report.schema.json).For payloads at every conformance level (L0 through L4), see examples/ — each file is the smallest report that satisfies its level.
For the full envelope and every primitive, see the 13-section spec.
What this is
ARP is AgentMinds' documented adoption of five existing agent / observability standards, plus one extension that fills a real gap. It is the wire format AgentMinds uses today, written down so external integrators don't have to reverse-engineer HTTP traffic.
If you are choosing between ARP and a real standard like OpenTelemetry GenAI or MCP, follow the standard. ARP is a profile of those standards optimized for AgentMinds' delivery surface — it is not an anchor for your own architecture.
Read the spec
- AGENT_REPORTING_PROFILE.md — full specification (13 sections)
- schemas/agent_report.schema.json — machine-readable JSON Schema (draft 2020-12)
- examples/ — concrete payloads for L0 / L2 / L3 / L4
- eval-set/v0-strawman.md — Eval set v0 strawman (open for delta; not normative until v1.0)
- CHANGELOG.md — version history
Latest version: v1.3.0
Released 2026-05-08 (live in this repo as the
v1.3.0tag). Minor release. Backwards-compatible — v1.2.x senders and collectors continue to work; new fields are additive.Spec additions
- §4.1.1
reversibility(B2) — closed-enum field on thePatternobject:safe_config/reversible_code/risky_infra/security_critical/null. Used by collectors and consumers as an auto-apply gating signal. Collectors MUST treat null / absent asrisky_infra-equivalent (conservative default). Lineage: blast-radius tags in deployment systems (Liquibase, SemVer breaking-change severity).
Reference collector additions (informative)
These describe the
agentmindsdev/agentmindscollector's delivery surface; they are not normative for the profile but are documented in §11.1 as worked examples.- B1 — Split top-rules arrays.
/personalized-rulesreturnstop_production_observedandtop_documentedas distinct arrays. The mixedtop_rulesarray is kept for backwards compatibility, slated for v1.4 removal. - A3 —
negative_evidencearray. Filtered patterns are now surfaced with explicit reason enum (site_type_mismatch_narrow/already_applied/non_english_content/low_confidence/bundle_size_exceeded). Consumers can render these as "we considered this but excluded it" UX, instead of silently dropping candidates. - F0 — Non-English content filter. The reference collector
filters non-English pattern submissions before scoring; rejected
candidates surface in
negative_evidencewith reasonnon_english_content.
spec_versionfield valueBackend responses (
/sync/me,/sync/personalized-rules,/sync/pool-stats) reportspec_version: "ARP-1.3.0"from this release onward. Earlier deployments returned"ARP-1.1"until the drift was reconciled inagentminds@2a2d5f0.Implementation status
Surface Version Live Spec (this repo) v1.3.0tag✓ Backend collector agentminds@a8c23b3+(api.agentminds.dev)✓ MCP server agentminds-mcp@1.3.2+(npm)✓ Node SDK @agentmindsdev/node@0.4.0+(npm)✓ Python SDK agentminds@0.5.0+(PyPI)✓ What's new in v1.2.2
- §11.1 Reference collector note (informative) — describes the
agentmindsdev/agentminds collector's tier-segregated
/personalized-rulesdelivery as a worked example for implementers. Not normative; collector behavior is profile-specific.
What's new in v1.2.1
Phase 2 of the v1.1 deepdive plan, additive over v1.0 / v1.1.x:
lifecycle_eventenvelope (cold_start / wake / scheduled / shutdown / running)Exceptionevidence shape (Sentry-alignedmechanism.handled)dotted_orderon telemetry spans (LangSmith-compatible)Handoffprimitive for multi-agent delegation eventsPromptManifestprimitive for prompt provenance- AGNTCY OASF skill ID cross-references +
agentskills.iolinkage - Cloudflare 5-tier
execution_tierenum + ARPin_processextension - MCP role disambiguation (
mcp_server_exposedvsmcp_clients_consumed[])
Full notes in CHANGELOG.md.
Live at
- Landing page (with examples and badges): agentminds.dev/profile
- Reference implementation: closed-source AgentMinds collector (agentminds.dev — pointers to the fingerprint helper, lifecycle migration, and filter glue are in §11 of the spec)
Used by
- agentminds.dev — reference implementation. A growing pool of patterns flows through the L3 envelope; live counters at agentminds.dev/showcase and agentminds.dev/status.
Adopters welcome — open a PR to add your project.
Lineage
Each row cites the upstream version ARP defers to. ARP version bumps require re-checking each upstream; if any absorbs an ARP primitive, see the Reorientation clause below.
Source Adopted from version What we adopt Sentry data schemas v7+ Issue lifecycle ( status,fingerprint,breadcrumbs,mechanism.handled)OpenTelemetry GenAI semconv 1.27+ (later versions compatible — namespace is additive) gen_ai.*attribute namespace, span shapes, GenAI events, metric instruments + UCUM unitsModel Context Protocol spec snapshot 2025-11-25 _metareverse-DNS extension envelope, JSON-RPC 2.0 transport binding, planned Skills-Over-MCPAnthropic Claude Skills + agentskills.io open spec SKILL.mdYAML frontmatterAGNTCY OASF v1+ Descriptor envelope, metric shape, observability data referencing, skill taxonomy IDs The five upstreams are independent; ARP layers them into a single envelope. Where they overlap, ARP defers to the more opinionated upstream (Sentry for issue lifecycle, OTel for telemetry).
For the full set of normative references (including OpenInference, Langfuse Score, and OpenAI Agents SDK), see §1.2 of the spec.
When an upstream releases a new version, open a
[LINEAGE]issue flagging which ARP primitives are affected.The single thing we own
§4.1 Pattern object — cross-site learned-pattern lifecycle.
Every pattern carries a stable fingerprint, a status (
active/solved/obsolete),first_seen/last_seen,applicable_site_types, and a confidence score. That single primitive is what enables AgentMinds' cross-site recommendation pool, and it is the only piece of ARP not directly inherited from the lineage.How we know nobody else covers this
A 2026-04 survey of adjacent specs found cross-site pattern lifecycle absent in each:
Spec Closest primitive Why it doesn't cover §4.1 OpenTelemetry GenAI gen_ai.*attributes on spansPer-call telemetry, not durable pattern objects with cross-site lifecycle Model Context Protocol Tool / resource registries Tools and resources, not failure-pattern catalogs AGNTCY OASF Agent descriptors + skill taxonomy Describes agents and skills, not what those agents learned across sites Sentry data schemas Issue lifecycle ( fingerprint,status)Single-tenant: issues belong to one project within one organization; no cross-customer pool primitive OWASP / CIS benchmarks Human-curated static rule packs (security baselines / CWE checks) Static rules, not agent-emitted patterns with per-fingerprint lifecycle and cross-site evidence aggregation Datadog Watchdog / New Relic AI Vendor-internal anomaly detection Proprietary engine, organization-scoped only, no open schema for re-implementation If you know of a spec that does cover this, please open an
[ARP-SPEC]issue — ARP should defer to it.Conformance levels
Level Required features L0 Envelope + report.summary+warnings[].messageL1 L0 + severity+category+statusper warningL2 L1 + fingerprint+first_seen+last_seen+countL3 L2 + memory.learned_patternswith §4.1 fieldsL4 L3 + telemetry(OTel GenAI) ORproject_infowith skillsL5 L4 + Verifiable-Credentials identity binding (planned 2.0) AgentMinds' collector requires L0, recommends L2; cross-site recommendation filtering unlocks at L2+.
A worked example for each level lives in examples/.
Reorientation clause
If any upstream standard absorbs the pattern-lifecycle primitive (§4.1) into its canonical spec, AgentMinds MUST publish ARP MAJOR+1 within 30 days that defers the primitive to the upstream definition. We are explicitly the fastest adopter of the winning standard, never the spec owner. See §7 of the spec for the formal versioning rule.
Contributing
Public comment, suggestions, and PRs welcome.
- General questions / use-case stories — open a Discussion. This is the right kind of door for "how would I use ARP for X?" or "is anyone else doing Y?" — not formal enough for an issue.
- Spec feedback — open an
[ARP-SPEC]issue for clarity / schema / new-primitive proposals. - Upstream version drift — open a
[LINEAGE]issue when an upstream we defer to (Sentry / OTel / MCP / Skills / OASF) releases a new version that may affect ARP. - Pull requests — typo / clarity / example fixes go straight to PR; schema changes need an issue first.
- External standards engagement — if you sit on the MCP working group, OTel GenAI SIG, AGNTCY observability WG, or related body, we'd love to hear how ARP can defer to your work.
License
This profile is released under CC-BY-4.0. Reuse and adapt freely; attribution to AgentMinds appreciated. See LICENSE for the full notice.
Suggested citation
AgentMinds (2026). AgentMinds Reporting Profile v1.3.0. CC-BY-4.0. https://github.com/agentmindsdev/profile
agent-pack-builder/skills/agent-reporting/references/arp/agent_report.schema.jsoncode · 24.3 KB · preview truncated
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://docs.agentminds.dev/schemas/agent_report.schema.json", "title": "AgentMinds Reporting Profile (ARP) v1.2.1", "description": "Wire format for agent reports, warnings, learned patterns, recommendations and skill manifests. See docs/AGENT_REPORTING_PROFILE.md. ARP is a profile built on Sentry + OTel GenAI + MCP + Claude Skills + AGNTCY OASF; it is NOT a competing standard.", "type": "object", "required": ["agent", "report"], "additionalProperties": true, "properties": { "arp_version": { "type": "string", "pattern": "^[0-9]+\\.[0-9]+(\\.[0-9]+)?$", "description": "Semver of the ARP profile the sender targets. Defaults to latest minor of same major." }, "ars_version": { "type": "string", "pattern": "^[0-9]+\\.[0-9]+(\\.[0-9]+)?$", "description": "Legacy alias for arp_version (pre-rename). Accepted for backwards compatibility; prefer arp_version on new payloads." }, "agent": { "type": "string", "minLength": 1, "maxLength": 64, "pattern": "^[a-z][a-z0-9_-]*$", "description": "Stable agent name. Lowercase, snake/kebab case." }, "site_id": { "type": "string", "minLength": 1, "maxLength": 64, "description": "Stable site identifier. May be set by the transport layer if absent in body." }, "session_id": { "type": "string", "minLength": 1, "maxLength": 128, "description": "Optional session/run identifier — correlates a sequence of agent invocations within one logical workflow. Compatible with LangSmith Threads and OpenInference session.id semantics." }, "user_id": { "type": "string", "minLength": 1, "maxLength": 128, "description": "Optional opaque user identifier (NOT PII — collectors should hash or pseudonymise upstream). Maps to OpenInference user.id." }, "conversation_id": { "type": "string", "minLength": 1, "maxLength": 128, "description": "Optional conversation/thread identifier. Alias of OTel gen_ai.conversation.id; multi-turn agent flows MAY use this to group reports." }, "_meta": { "type": "object", "additionalProperties": true, "description": "ARP §2.1 (v1.1): vendor extension envelope using reverse-DNS namespacing (e.g. com.agentminds.*, io.agentminds.*). MCP-aligned. Open by design; collectors MUST ignore unknown keys. Reserved second-label namespaces: agentminds.*, arp.*." }, "lifecycle_event": { "type": "string", "enum": ["cold_start", "wake", "scheduled", "shutdown", "running"], "description": "ARP §2.2 (v1.2): OPTIONAL signal for hibernate-aware runtimes (Cloudflare Agents Durable Object, AWS Lambda cold start, etc.). Affects warning interpretation — fresh wake-up warnings carry less weight than steady-state ones. MUST NOT be required for non-hibernating agents." }, "report": { "$ref": "#/$defs/Report" }, "memory": { "$ref": "#/$defs/Memory" }, "telemetry": { "$ref": "#/$defs/Telemetry" }, "project_info": { "$ref": "#/$defs/ProjectInfo" }, "schema": { "type": "object", "properties": { "name": { "type": "string" }, "version": { "type": "string" } } } }, "$defs": { "Severity": { "type": "string", "enum": ["fatal", "error", "warning", "info", "debug"] }, "WarningSeverity": { "type": "string", "enum": ["critical", "high", "medium", "low", "info"] }, "WarningStatus": { "type": "string", "enum": ["unresolved", "resolved", "ignored", "muted"], "default": "unresolved" }, "PatternStatus": { "type": "string", "enum": ["active", "solved", "obsolete"], "default": "active" }, "RecommendationStatus": { "type": "string", "enum": ["open", "applied", "dismissed"], "default": "open" }, "Priority": { "type": "string", "enum": ["critical", "high", "medium", "low"] }, "Effort": { "type": "string", "enum": ["trivial", "small", "medium", "large"] }, "Impact": { "type": "string", "enum": ["critical", "high", "medium", "low"] }, "Category": { "type": "string", "enum": [ "performance", "security", "content", "seo", "quality", "compliance", "infra", "general" ] }, "Fingerprint": { "description": "ARP fingerprint identity. Either a single lowercase hex SHA-256 string (canonical ARP form), or an array of strings with optional `{{ default }}` placeholder (Sentry-aligned form, v1.1+). Collectors MUST accept either; producers SHOULD pick one form per payload.", "oneOf": [ { "type": "string", "pattern": "^[0-9a-f]{64}$", "description": "Canonical ARP — lowercase hex SHA-256 (64 chars)." }, { "type": "array", "minItems": 1, "items": { "type": "string", "minLength": 1 }, "description": "Sentry-aligned array form — segments concatenated server-side. May include the literal `{{ default }}` placeholder at any position to inherit the SDK's default fingerprint." } ] }, "Timestamp": { "type": "string", "format": "date-time", "description": "RFC 3339 UTC timestamp." }, "Score": { "description": "ARP §3.5 (v1.1): evaluation score primitive. Lineage: Langfuse Score model + LangSmith Feedback. Lets collectors carry NUMERIC / CATEGORICAL / BOOLEAN evaluation outcomes attached to warnings, patterns, or runs without overloading Recommendation.confidence.", "type": "object", "required": ["key", "data_type", "value"], "additionalProperties": true, "properties": { "fingerprint": { "$ref": "#/$defs/Fingerprint" }, "key": { "type": "string", "minLength": 1, "description": "Short stable identifier, e.g. 'hallucination_check'." }, "data_type": { "type": "string", "enum": ["numeric", "categorical", "boolean"], "description": "Closed enum — keep this small, no vendor extensions." }, "value": { "description": "Number for data_type=numeric, string for categorical, boolean for boolean.", "oneOf": [{ "type": "number" }, { "type": "string" }, { "type": "boolean" }] }, "comment": { "type": "string", "description": "Optional long-form rationale." }, "name": { "type": "string", "description": "Human-readable label." }, "warning_fingerprints": { "type": "array", "items": { "$ref": "#/$defs/Fingerprint" } }, "pattern_fingerprints": { "type": "array", "items": { "$ref": "#/$defs/Fingerprint" } }, "compared_to_baseline_id": { "type": "string", "description": "Optional baseline run identifier for comparative scoring." }, "_meta": { "type": "object", "additionalProperties": true } } }, "Exception": { "description": "ARP §3.7 (v1.2): structured exception payload. Sentry-aligned. Goes inside Warning.evidence.exception when an agent reports a thrown/caught error. Distinguishes handled vs uncaught for triage.", "type": "object", "additionalProperties": true, "properties": { "type": { "type": "string", "description": "Exception class name, e.g. 'ValueError', 'TimeoutError'." }, "value": { "type": "string", "description": "Stringified exception message." }, "module": { "type": "string", "description": "Importable module path." }, "stacktrace": { "type": "object", "additionalProperties": true }, "mechanism": { "type": "object", "additionalProperties": true, "properties": { "handled": { "type": "boolean", "description": "True = caught by agent's try/except. False = uncaught (reached the top of the stack)." }, "type": { "type": "string", "description": "How the exception entered the report: 'exception_handler' / 'signal' / 'unhandled' / etc." } } } } }, "Breadcrumb": { "description": "ARP §3.6 (v1.1.1): timestamped event leading up to a Warning. Sentry-aligned. Critical for understanding cascade failures.", "type": "object", "required": ["timestamp", "type"], "additionalProperties": true, "properties": { "timestamp": { "$ref": "#/$defs/Timestamp" }, "type": { "type": "string", "enum": ["navigation", "http", "error", "info", "query", "ui", "user", "default"] }, "category": { "type": "string", "description": "Free-form category, e.g. 'console', 'fetch', 'agent.call'." }, "message": { "type": "string", "description": "Human-readable description of the event." }, "level": { "$ref": "#/$defs/Severity" }, "data": { "type": "object", "additionalProperties": true, "description": "Free-form structured data attached to the breadcrumb." } } }, "Report": { "type": "object", "required": ["summary"], "additionalProperties": true, "properties": { "severity": { "$ref": "#/$defs/Severity" }, "summary": { "type": "string", "minLength": 1 }, "score": { "type": "number", "minimum": 0, "maximum": 100, "description": "Optional 0-100 health score for the agent run." }, "metrics": { "type": "object", "additionalProperties": true }, "warnings": { "type": "array", "items": { "$ref": "#/$defs/Warning" } }, "recommendations": { "type": "array", "items": { "$ref": "#/$defs/Recommendation" } }, "scores": { "type": "array", "items": { "$ref": "#/$defs/Score" }, "description": "ARP §3.5 (v1.1): evaluation scores attached to this report. Use Score for typed eval outcomes; the legacy `report.score` 0-100 health number is for one-off summaries only." }, "handoffs": { "type": "array", "items": { "$ref": "#/$defs/Handoff" }, "description": "ARP §6.2 (v1.2): multi-agent delegation events that occurred during this report. OpenAI Agents SDK Handoff lineage." }, "_meta": { "type": "object", "additionalProperties": true } } }, "Handoff": { "description": "ARP §6.2 (v1.2): one multi-agent delegation event. Lineage: OpenAI Agents SDK `Handoff` class.", "type": "object", "required": ["from_agent", "to_agent"], "additionalProperties": true, "properties": { "from_agent": { "type": "string", "minLength": 1 }, "to_agent": { "type": "string", "minLength": 1 }, "trigger": { "type": "string", "description": "Human-readable reason for the handoff." }, "tool_name_override": { "type": "string" }, "input_filter": { "type": "string", "description": "Optional regex/spec describing how the input is filtered before delegation." }, "nest_handoff_history": { "type": "boolean" }, "occurred_at": { "$ref": "#/$defs/Timestamp" }, "_meta": { "type": "object", "additionalProperties": true } } }, "PromptManifest": { "description": "ARP §6.3 (v1.2): prompt provenance. Lineage: OpenInference prompt.* attributes + LangSmith Prompt Hub.", "type": "object", "additionalProperties": true, "properties": { "vendor": { "type": "string", "description": "e.g. 'langsmith', 'openai', 'self', 'anthropic-prompts'" }, "id": { "type": "string" }, "version": { "type": "string" }, "url": { "type": "string", "format": "uri" }, "template": { "type": "string", "description": "Inline template body. Senders SHOULD provide either url OR template." }, "variables": { "type": "object", "additionalProagent-pack-builder/skills/agent-reporting/scripts/validate.mjscode · 6.7 KB
#!/usr/bin/env node // validate.mjs — validator for this pack's agent-report profile (ARP v1.2.1 // adoption, conformance target L2). // // This is a PROFILE check, not a full JSON-Schema engine: it enforces exactly the // items this profile commits to (required fields, enums, fingerprint and timestamp // shapes). The vendored normative schema lives at // references/arp/agent_report.schema.json (CC-BY-4.0, unmodified). // // Only the comments above were adapted for this pack; the validation logic below // is unchanged from the source profile. // // Usage: node scripts/validate.mjs <file.json> [more.json ...] // Exit: 0 when every file is valid ("N report(s) valid"), 1 with per-file problems. import { readFileSync } from "node:fs"; const SEVERITY = ["fatal", "error", "warning", "info", "debug"]; // report.severity / warning.level const WARNING_SEVERITY = ["critical", "high", "medium", "low", "info"]; // warning.severity const WARNING_STATUS = ["unresolved", "resolved", "ignored", "muted"]; const CATEGORY = ["performance", "security", "content", "seo", "quality", "compliance", "infra", "general"]; const RECOMMENDATION_STATUS = ["open", "applied", "dismissed"]; const PRIORITY = ["critical", "high", "medium", "low"]; const EFFORT = ["trivial", "small", "medium", "large"]; const PATTERN_STATUS = ["active", "solved", "obsolete"]; const AGENT_RE = /^[a-z][a-z0-9_-]*$/; const HEX64_RE = /^[0-9a-f]{64}$/; // RFC 3339 instant as ARP uses it (UTC "Z" form; offsets also legal). const TS_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/; const isObj = (v) => typeof v === "object" && v !== null && !Array.isArray(v); const isStr = (v) => typeof v === "string" && v.length > 0; const isInt = (v, min = 0) => Number.isInteger(v) && v >= min; const inEnum = (list, v) => list.includes(v); const isFingerprint = (v) => isStr(v) && (HEX64_RE.test(v) || (Array.isArray(v) && v.length > 0 && v.every(isStr))); function validate(report) { const problems = []; const need = (cond, path, msg) => { if (!cond) problems.push(`${path}: ${msg}`); }; need(isObj(report), "$", "report must be an object"); if (!isObj(report)) return problems; need(isStr(report.arp_version), "arp_version", "required, non-empty string (we emit \"1.2.1\")"); need(isStr(report.agent) && AGENT_RE.test(report.agent) && report.agent.length <= 64, "agent", 'required, lowercase slug matching ^[a-z][a-z0-9_-]*$ (max 64)'); const r = report.report; need(isObj(r), "report", "required object"); if (isObj(r)) { need(isStr(r.summary), "report.summary", "required, non-empty sentence(s)"); if (r.severity !== undefined) need(inEnum(SEVERITY, r.severity), "report.severity", `one of ${SEVERITY.join("|")}`); if (r.score !== undefined) need(typeof r.score === "number" && r.score >= 0 && r.score <= 100, "report.score", "number 0-100"); if (r.metrics !== undefined) need(isObj(r.metrics), "report.metrics", "object"); for (const [i, w] of (r.warnings ?? []).entries()) { const p = `report.warnings[${i}]`; need(isObj(w), p, "object"); if (!isObj(w)) continue; need(isStr(w.message), `${p}.message`, "required, non-empty"); if (w.fingerprint !== undefined) need(isFingerprint(w.fingerprint), `${p}.fingerprint`, "hex sha256 or string array"); if (w.level !== undefined) need(inEnum(SEVERITY, w.level), `${p}.level`, `one of ${SEVERITY.join("|")}`); if (w.severity !== undefined) need(inEnum(WARNING_SEVERITY, w.severity), `${p}.severity`, `one of ${WARNING_SEVERITY.join("|")}`); if (w.status !== undefined) need(inEnum(WARNING_STATUS, w.status), `${p}.status`, `one of ${WARNING_STATUS.join("|")}`); if (w.category !== undefined) need(inEnum(CATEGORY, w.category), `${p}.category`, `one of ${CATEGORY.join("|")}`); for (const t of ["first_seen", "last_seen"]) { if (w[t] !== undefined) need(isStr(w[t]) && TS_RE.test(w[t]), `${p}.${t}`, "RFC 3339 timestamp"); } if (w.count !== undefined) need(isInt(w.count, 1), `${p}.count`, "integer >= 1"); } for (const [i, rec] of (r.recommendations ?? []).entries()) { const p = `report.recommendations[${i}]`; if (!isObj(rec)) { problems.push(`${p}: object`); continue; } need(isStr(rec.title), `${p}.title`, "required, non-empty"); if (rec.fingerprint !== undefined) need(isFingerprint(rec.fingerprint), `${p}.fingerprint`, "hex sha256 or string array"); if (rec.priority !== undefined) need(inEnum(PRIORITY, rec.priority), `${p}.priority`, `one of ${PRIORITY.join("|")}`); if (rec.category !== undefined) need(inEnum(CATEGORY, rec.category), `${p}.category`, `one of ${CATEGORY.join("|")}`); if (rec.effort !== undefined) need(inEnum(EFFORT, rec.effort), `${p}.effort`, `one of ${EFFORT.join("|")}`); if (rec.confidence !== undefined) need(typeof rec.confidence === "number" && rec.confidence >= 0 && rec.confidence <= 1, `${p}.confidence`, "number 0-1"); if (rec.status !== undefined) need(inEnum(RECOMMENDATION_STATUS, rec.status), `${p}.status`, `one of ${RECOMMENDATION_STATUS.join("|")}`); } } if (report.memory !== undefined) { need(isObj(report.memory), "memory", "object"); if (isObj(report.memory)) { if (report.memory.total_runs !== undefined) need(isInt(report.memory.total_runs), "memory.total_runs", "integer >= 0"); for (const [i, pat] of (report.memory.learned_patterns ?? []).entries()) { const p = `memory.learned_patterns[${i}]`; if (!isObj(pat)) { problems.push(`${p}: object`); continue; } need(isStr(pat.pattern), `${p}.pattern`, "required, non-empty"); if (pat.fingerprint !== undefined) need(isFingerprint(pat.fingerprint), `${p}.fingerprint`, "hex sha256 or string array"); if (pat.status !== undefined) need(inEnum(PATTERN_STATUS, pat.status), `${p}.status`, `one of ${PATTERN_STATUS.join("|")}`); } } } if (report._meta !== undefined) need(isObj(report._meta), "_meta", "object"); return problems; } const files = process.argv.slice(2); if (files.length === 0) { console.error("usage: node scripts/agent-report/validate.mjs <file.json> [more.json ...]"); process.exit(2); } let ok = 0; let bad = 0; for (const f of files) { let parsed; try { parsed = JSON.parse(readFileSync(f, "utf8")); } catch (err) { console.error(`${f}: not valid JSON (${err.message})`); bad += 1; continue; } const problems = validate(parsed); if (problems.length === 0) { ok += 1; console.log(`${f}: valid (L2 profile)`); } else { bad += 1; console.error(`${f}: ${problems.length} problem(s)`); for (const p of problems) console.error(` - ${p}`); } } if (bad > 0) { console.error(`${ok} valid, ${bad} invalid`); process.exit(1); } console.log(`${ok} report(s) valid`);agent-pack-builder/skills/agent-reporting/templates/report-template.jsoncode · 1.3 KB
{ "arp_version": "1.2.1", "agent": "your-agent", "report": { "severity": "info", "summary": "One or two plain sentences: what the agent did this period, and what (if anything) is stuck.", "score": 100, "metrics": { "tasks_completed": 0, "runs": 0, "wall_time_minutes": 0 }, "warnings": [ { "fingerprint": "0000000000000000000000000000000000000000000000000000000000000000", "message": "Example warning — replace with a real one, or delete this array entry", "level": "info", "severity": "low", "status": "unresolved", "category": "general", "first_seen": "2026-01-01T00:00:00Z", "last_seen": "2026-01-01T00:00:00Z", "count": 1 } ], "recommendations": [ { "fingerprint": "0000000000000000000000000000000000000000000000000000000000000000", "title": "Example recommendation — replace or delete", "details": "What to do, why, and how you would know it worked.", "priority": "low", "category": "general", "effort": "small", "confidence": 0.5, "status": "open" } ] }, "memory": { "schema_version": "1.2.1", "total_runs": 0, "learned_patterns": [] }, "_meta": { "dev.talentdelta.period": { "from": "2026-01-01", "to": "2026-01-07" } } }agent-pack-builder/skills/agent-self-inventory/SKILL.mdmarkdown · 4.5 KB
name: agent-self-inventory description: "Use when packing an agent you already run — inventory its identity, behaviour, skills and tools, then decide what ships and what stays behind."
Agent self-inventory — from a working agent to a pack
Authoring a pack for an agent that already runs is mostly subtraction. The agent already has an identity, habits, skills and tools; your job is to find them, decide which are the agent and which are the operator, and generalise the rest until a stranger could run it.
When to use
A pack built from a live agent (your own, or one your operator runs), rather than from a written brief. Also use it as the first pass when a brief says "make a pack like the agent we have".
1. Inventory the live agent
Read what the agent actually is, not what it is described as. Gather all of it before you write a single line of the pack:
Source What you are looking for SOUL.md/ profile promptIts stated goal, style and authority — and where they disagree with behaviour. config.yaml+ envProvider, model, memory provider, tool/MCP wiring, and anything secret. skills/Each skill's trigger and what it really does; which ones depend on each other. Tools & MCP servers What it can reach, and what it needs credentials for. Scheduled jobs Anything it runs on a timer — reusable cadence vs operator-specific chore. Memory / notes Durable preferences and learned quirks worth stating as rules. Its operator's instructions House rules, guardrails, forbidden actions, standing refusals. 2. Split the agent from its context
Every item lands in exactly one of three buckets:
- Ships — generic behaviour, reusable procedure, identity, tool requirements, usage docs.
- Generalises — real work, but tied to one operator, client, domain or machine. Rewrite with placeholders and keep the pattern; the pattern is the value.
- Stays behind — private context, personal data, credentials, licensed-in content, machine paths, internal names, and anything true only of this installation.
The test for a skill: if it only works for one operator, it is a task, not a skill. A task does not ship.
3. Extract in the pack's own voice
- Identity → SOUL.md, three paragraphs: goal, style, authority. Never paste the live SOUL: it usually carries operator context and process that belongs in skills.
- Behaviour → skills. One concern per skill, a
descriptionthat says when to use it. - Capabilities and requirements → the README's "what's included" and quickstart.
- Tools and credentials → named as requirements, never as values.
HINDSIGHT_API_KEYis a name; the key itself is not yours to ship. - Standing guardrails → authority in SOUL.md, and repeated in the README if they are load-bearing.
4. Interview the operator (four questions)
- What must always hold, whatever else changes?
- What may the agent never do — and who decides when it is unsure?
- What runtime does the pack need (Hermes version, provider, memory, tools)?
- What must not leave this machine, even in generalised form?
Question 4 is the one that produces the removals list. Write that list down as you go; declaring what you removed is part of the deliverable, not an afterthought.
5. Prove it by running the quickstart
The pack is done when a fresh profile can follow the README with no prior knowledge:
- Create a clean profile and install the pack exactly as the quickstart says.
- Ask the agent to do one thing from each skill's "when to use" line.
- Note every hesitation, missing file and unstated assumption — those are README defects.
- Fix the README (not the new profile) and repeat once.
Then hand it to
agent-pack-authoringfor the scrub, classification and packaging pass.Pitfalls
- Shipping the live SOUL verbatim — it leaks operator context and reads as a briefing, not an identity.
- Describing what the agent was meant to do instead of what it does. If behaviour and documentation disagree, document the behaviour and flag the gap to the operator.
- Keeping a real skill name, client or domain "just as an example" — an example is a leak with a friendly label. Use an invented one.
- Generalising a credential into a placeholder-less requirement. Name the variable, never a value, and never a real token even in a commented line.
- Declaring no removals. Every live agent has context that did not ship; a pack claiming an empty removals list after being built off a working agent has not been looked at properly.