Skip to content
Night Owls.dev
Jump to a page

@nightowlsdev/agent-builder

Pre-built agents

The meta-agent that knows the nightowls agent anatomy end to end: researches external skills, drafts + validates agents/bundles, and, behind a rule-enforced human-approval floor, imports skills and publishes definitions.

What it does

@nightowlsdev/agent-builder ships an agent whose persona encodes the framework's own internals (agent anatomy, the three skill kinds, bundles, the actor model, with a compile-time staleness guard that fails this package's CI if core's shape changes). With no options it is DRAFT-ONLY: it designs and validates agents/bundles through the real defineAgent/defineBundle and a human applies the JSON. Give it providers + repos + a service actor and it gains gated tools: search_skills/preview_skill (never raw provider I/O, the skills package's policy gates run before any fetch; everything third-party arrives fenced), list/get_agent, import_skill/publish_agent/publish_bundle. The mutating tools are hard-coded needsApproval + failClosed AND floored to `ask` by a package-attached enforce-level rule, engine-tested that a permissive host hook cannot downgrade the gate, with your policyGuard running fail-closed before every repo call. The storage actor bar (agents can never mutate definitions) stays fully intact underneath: publishes run with YOUR service actor, only after a human approves that specific call.

Install

pnpm add @nightowlsdev/agent-builder

Key exports

  • createBuilder (draft-only safe default; capability tools appear with their dependencies)
  • builderApprovalRule (the enforce-level ask floor on the mutating tools)
  • AGENT_DRAFT_SCHEMA / BUNDLE_DRAFT_SCHEMA / validateAgentDraft / validateBundleDraft
  • manifest / BUILDER_CURATED_SKILLS (skill-creator, writing-skills, writing-great-skills, pinned)

Usage

agent-builder.ts
import { createBuilder } from "@nightowlsdev/agent-builder";
import { skillsShProvider } from "@nightowlsdev/skills";

// DRAFT-ONLY by default: designs + validates agents/bundles; a human applies the JSON.
const builder = createBuilder();

// Full capability: gated skill research + human-approved publishing. Every mutating call suspends
// for approval (an enforce-level rule a permissive host hook cannot downgrade), then runs YOUR
// service actor through your policyGuard, the agents-can-never-mutate storage bar stays intact.
const fullBuilder = createBuilder({
  providers: { "skills.sh": skillsShProvider() },
  storage: {
    skills: storage.skills, skillsWritable: storage.skillsWritable,
    agents: storage.agents, agentsWritable: storage.agentsWritable,
    bundles: storage.bundles, bundlesWritable: storage.bundlesWritable, // enables publish_bundle
  },
  actor: { type: "service", serviceId: "builder-host", tenantId },
  policy: { allowAuthors: ["anthropics", "vercel-labs", "coreyhaines31"] },
  policyGuard: (op) => assertOrgAllows(op),   // throw to deny, fail-closed
});

// PREREQUISITE: your host handles suspend/resume (approvals render as question cards).
// The full journey: /docs/adopt-prebuilt-agents

What it provides

agent-builder is a meta-agent whose persona encodes the framework's own internals — agent anatomy, the three skill kinds, bundles, the actor model — with a compile-time staleness guard that fails this package's CI if core's shape changes. With no options it is DRAFT-ONLY: it designs and validates agents/bundles through the REAL defineAgent/defineBundle and a human applies the emitted JSON. Given providers + repos + a service actor it gains capability tools to research external skills and, behind a rule-enforced human-approval floor, import skills and publish definitions.

When to use it

  • You want an in-product 'design me an agent / bundle' experience that produces framework-valid definitions, not free text.
  • You want gated skill research (search_skills / preview_skill) and governed publishing behind human approval, under your own service actor and policy guard.
  • You are building an authoring/workshop surface and need the mutating operations to be un-downgradeably gated.

When not to

  • You author agents in code — defineAgent / defineBundle directly is simpler; the builder's value is the guided, validated, gated authoring loop.
  • Your host can't handle suspend/resume — the mutating tools suspend for approval and simply park without an approval surface.
  • You only need to import curated skills, not design new agents — agent-kit's importCuratedSkills is the narrower tool.

Alternatives

  • defineAgent / defineBundle in coreYou author agents in code and review them in PRs — no conversational drafting agent, no in-product publishing, no approval surface needed.
  • agent-kit lifecycle helpersYou want to seed/upgrade a known pre-built agent on a persisted store (ensurePrebuiltAgent / publishPrebuiltAgent), not design brand-new agents interactively.

Strengths

  • Safe default: createBuilder() with no storage/actor/providers is DRAFT-ONLY — it designs and validates; a human applies. Capability tools appear only when their dependencies are supplied.
  • The approval floor is rule-enforced, not flag-hoped: mutating tools are hard-coded needsApproval + failClosed AND floored to 'ask' by a package-attached enforce-level rule, engine-tested that a permissive host preToolCall hook cannot downgrade it.
  • Drafts validate through the REAL framework — AGENT_DRAFT_SCHEMA / BUNDLE_DRAFT_SCHEMA + validateAgentDraft / validateBundleDraft run zod plus the actual defineAgent/defineBundle, so a draft that validates is a definition that will load.
  • import_skill requires the previewed expectedName (+ optional expectedSourceVersion) — what's imported is exactly what was reviewed, and third-party text always arrives fenced.
  • The storage actor bar stays intact: publishes run with YOUR service actor, only after a human approves that specific call — the agent can never mutate definitions on its own.

Limits & trade-offs

  • The mutating tools suspend for approval (SP5) — a headless host must catch and resume the suspend, or publishing parks forever.
  • Bundle drafts don't yet cover per-member rules/workflows — those handles are host-side, attached after the draft is applied.
  • No hosted approve/publish UI ships — the OSS tools exist; the 'Agent Workshop' surface is host-built.
  • It is only as safe as your configuration — policy.allowAuthors and a fail-closed policyGuard are yours to set before any fetch or repo mutation.

How it works

createBuilder assembles the framework-internals persona plus a tool set that grows with the dependencies you supply: providers enable search_skills / preview_skill, adding the writable skill store enables import_skill, adding agent/bundle repos enables publish_agent / publish_bundle. Every mutating tool is built needsApproval + failClosed, and the package attaches builderApprovalRule — an enforce-level rule forcing 'ask' on exactly the PRESENT mutating tools — so defineSwarm wires the composed mostRestrictiveTool path a permissive host hook can't downgrade. Third-party skill text arrives fenced through the skills package's policy gates; your policyGuard runs fail-closed before every repo mutation, and publishes execute under your service actor once the human approves.

Examples

Draft-only default

No storage/actor/providers — designs + validates only; a human applies the emitted JSON.

agent-builder-example-1.ts
import { createBuilder } from "@nightowlsdev/agent-builder";

const builder = createBuilder();

Validate a draft through the real framework

zod + the real defineAgent; returns publishable content or a legible error string.

agent-builder-example-2.ts
import { validateAgentDraft } from "@nightowlsdev/agent-builder";

const result = validateAgentDraft({
  slug: "triage",
  role: "specialist",
  personality: "Route inbound issues to the right owner.",
  externalSkillNames: ["issue-triage"],   // stored-skill grants; code skills are the developer's side
});

if ("error" in result) throw new Error(result.error);
// result.content is a publishable AgentVersionContent

Full-capability builder: gated research + human-approved publishing

Tools appear with their dependencies; policyGuard throws to deny, fail-closed.

agent-builder-example-3.ts
import { createBuilder } from "@nightowlsdev/agent-builder";
import { skillsShProvider } from "@nightowlsdev/skills";

const builder = createBuilder({
  providers: { "skills.sh": skillsShProvider() },
  storage: {
    skills: storage.skills, skillsWritable: storage.skillsWritable,
    agents: storage.agents, agentsWritable: storage.agentsWritable,
    bundles: storage.bundles, bundlesWritable: storage.bundlesWritable, // enables publish_bundle
  },
  actor: { type: "service", serviceId: "builder-host", tenantId },
  policy: { allowAuthors: ["anthropics", "vercel-labs"] },
  policyGuard: (op) => assertOrgAllows(op),   // throw to deny — fail-closed
});

Doing the parts it doesn't support

  • Publishing from a headless hostThe mutating tools suspend for approval. A headless host must catch the suspend (swarm.question) and drive a resume with the human's decision — @nightowlsdev/react hosts already render approvals as question cards.
  • Per-member rules/workflows in a bundle draftBundle drafts cover members plus declared dependencies; attach per-member rules/workflows host-side with defineBundle after the draft is applied.
  • Restricting which authors can be importedPass policy.allowAuthors (an allowlist) and a policyGuard that throws to deny — both run fail-closed before any fetch or repo mutation.

Related

  • agent-kitThe shared foundation the builder builds on — the manifest shape, curated import, and the lifecycle a publish lands into.
  • skillsThe SkillProvider + import policy the builder's search_skills / preview_skill / import_skill run through, fenced and gated.
  • coredefineAgent / defineBundle / defineRule — the real primitives the drafts validate against and the approval rule enforces on.
  • approval-modesHow the enforce-level 'ask' floor folds with a host's approval modes so mutations can only tighten.
  • capability-bundlesWhat publish_bundle emits — a reusable, closure-validated crew definition.