Scripts as a First-Class Tool Category
Agents always have permission to write and execute scripts. The prior art says a curated skill library beats re-deriving tool-call chains — 80–98% token reductions, 3.3× more items, 15.3× faster milestones. This paper wires that literature to a proposed Nexartis library: nexartis-agent-scripts, a pnpm monorepo of runtime-portable skill packages with a 5-step publish gate.
Problem
Agents that orchestrate every tool call turn-by-turn burn tokens, turns, and accuracy that a short script would save. The workspace AGENTS convention already grants agents permission to write and execute scripts; what is missing is a curated library so the good scripts compound instead of evaporating at session end.
Ship nexartis-agent-scripts, a pnpm monorepo of skill packages (SKILL.md + scripts/ + test/ + references/) built to the Agent Skills open spec with Nexartis extensions for runtime portability and verify pairing. Publish gate: tsc · vitest · publint · attw · wintertc-check (ast-grep) · tri-runtime smoke (Node + Miniflare + JSDOM). Discovery via ChunkHound-indexed frontmatter (progressive disclosure). scripts:sync mirrors to ~/.config/kilo/skills/. No fallbacks per the workspace no-hidden-behaviour principle — missing runtime capability is a classified error, not a silent alternative path.
Prior art — the numbers that justify the direction
- Anthropic — Code Execution with MCP + Programmatic Tool Calling — 85–98% token reduction reported on multi-tool workflows when agents write TypeScript that composes MCP calls instead of the LLM orchestrating each call turn-by-turn. open-ptc-agent is the reference implementation. The strongest published evidence that scripts-as-tools is not stylistic preference — it is a step change in efficiency for anything with more than a few tool hops.
- Cloudflare — Code Mode + Dynamic Worker Loader — 80% token reduction claimed for the code-mode-vs-tool-calls comparison. V8 isolates spin up ~100× faster than containers (sub-second sandboxes). Capability-based bindings + globalOutbound: null give a deny-by-default sandbox without a separate policy layer. The runtime that makes speculative + parallel execution cheap enough to be the default. Sub-second sandboxes are what turns "the agent writes a script" from a novelty into a hot path.
- Anthropic — Agent Skills open specification — Open spec: SKILL.md frontmatter (name, description, when-to-use) + scripts/ + references/ + progressive disclosure (name+description in the always-loaded index, body loaded on match). The interoperable envelope. If we author skills to this spec, they are portable across harnesses and discoverable by any agent that reads the spec.
- Voyager (NeurIPS 2023) — LLM skill library in Minecraft — 3.3× more distinct items collected, 15.3× faster milestone completion vs baselines. The mechanism is a growing library of small executable skills the agent both retrieves and extends. The canonical result that a curated skill library outperforms re-deriving from first principles turn after turn. The delta is not marginal — it is the difference between reaching the milestone and not.
- CodeAct (ICML 2024) — +20% task success and −30% conversation turns vs JSON-tool-call baselines by having the agent emit executable Python and observing the execution result each turn. This is the source frequently cited (via smolagents) as "code-as-actions is ~30% better". Underlying evidence that even ignoring token cost, the accuracy of code-as-actions beats orchestrated tool calls. Complements the token argument with a correctness argument.
- Hugging Face smolagents — CodeAgent — Popularised the "code agents are ~30% better than tool-calling agents" summary of CodeAct in production practice. The most commonly cited secondary source; useful to point at when explaining the direction to teams that have not read the original paper.
Production example already in the workspace
The pattern is not aspirational. Two live examples ground the architecture below: a curated fixture pipeline and the standing telemetry entry point. Both are small, composable, version-addressable scripts invoked by name — the shape a skill package will take.
- Reusable fixture pipeline (ozzydev-native-write-mcp) — mcp/servers/ozzydev-native-write-mcp/experiment/ ships four cooperating TypeScript scripts — mine-real-edits.mts, fetch-commitpackft.mts, curate-r5.mts, and a shared fixture-synthesis.mts — that mine and curate reusable edit fixtures. Each is a small, versioned, executable artefact composed by the agent, not orchestrated turn-by-turn.
- Telemetry emission (bin/telemetry-emit.mjs) — nexartis-ozzydev/bin/telemetry-emit.mjs is the standing scripts-as-tools entry point for session_report, tool events, and experiment records. Waves invoke it directly (pnpm run telemetry:emit) rather than teaching the model to POST JSON every turn — the D8 write-rubric case for scripted work.
Skills, not raw CLI — the agent-definition principle
Agents are defined by what runs inside a Cubicle: traceability, auditability, selective disclosure, and private memory/prompt history are load-bearing product properties. The model is declared in KYM. Every capability is mapped to a versioned skill, not raw CLI access — "better grep" is a skill version bump. Permissions and capability management key on (agent-card, skill-name, version-range); MAB experiments key on the same tuple. Raw shell-out to the host is a category error, not a fast path.
- Cubicle-bounded execution — Every capability runs inside a Cubicle: full traceability, auditability, selective disclosure, private per-agent memory/prompt history. Nothing an agent does escapes the Cubicle envelope; nothing observable outside the receipt store leaks in. The Cubicle IS the isolation and audit boundary. Raw CLI access to the host defeats every trust property the platform sells; skills-only defends them by construction.
- Model declared in KYM — The agent card in KYM names its model, its skill set, its permitted MCPs, its runtime host. Skills the agent is allowed to invoke are enumerated on the card; the Cubicle enforces the enumeration at execution time. Declaring the model in KYM keeps the receipt-and-eval loop honest — a receipt for a run is meaningful only if the model + skills combination it names is verifiable against KYM.
- Every capability is a versioned skill (not a raw CLI shell-out) — Anything an agent can do — better grep, run a build, deploy a worker, sign a receipt — is a skill package at a specific version. "Better grep" is a skill version bump, not a new argument to a shell tool. The skill body is progressive-disclosure text; the executable is a scripted, publish-gated artefact. The whole class of "agent typed rm -rf" failures disappears when there is no free-form shell. Skill versions are addressable, receiptable, benchable — a raw CLI call is none of those.
- Permissions + capability management key on skill+version — The permission model grants or denies at (agent-card, skill-name, version-range) granularity. Rolling out a new skill version is a permissions event; the grant is versioned alongside the skill. Receipts record which skill+version actually ran. Precise revocation. A skill version that fails a security review is denied without disturbing prior versions still in use.
- MAB experiments key on skill+version — The harness-bandit / experiment-variants design already accommodates arm = (agent-card, skill-set, skill-versions, harness). Comparing skill v1 vs v2 with everything else fixed is a first-class experiment; the receipt store slices by skill+version out of the box. A skill upgrade is a testable hypothesis, not a silent replacement. Same substrate as the harness-vs-harness bakeoff; different projection.
Runtime portability — the contract
The portable surface is WinterTC Minimum Common API, the Ecma TC55 standard-track effort. Anything a skill uses outside that surface must be declared in frontmatter; the publish gate enforces the declaration via an ast-grep rule set (wintertc-check).
- WinterTC Minimum Common API (Ecma TC55) — The portable JavaScript surface across server-side runtimes — Node, Deno, Bun, Cloudflare Workers, EdgeRuntime, etc. Standard-track, not a vendor promise. Targeting min-common-api is the difference between a skill that runs everywhere and a skill that quietly breaks in a Worker. This is our portability contract.
- tsup DEPRECATED → tsdown (Rolldown) or unbuild — tsup is discontinued. tsdown (Rolldown-backed) is the current-generation TS bundler; unbuild is the alternative for library-shaped output. Fresh baselines should never adopt a deprecated bundler. Both replacements are faster and actively maintained.
- publint + are-the-types-wrong (attw) — Static gates for package.json hygiene and TS types-vs-runtime consistency. Both are cheap to run in CI. A skill package that lies about its exports is worse than a skill that does not ship. These gates catch the whole class of "works on my machine" failures before they land.
- Feature-detect + fail-loud (no fallbacks per AGENTS §2) — Every skill starts with feature detection (crypto, streams, fetch flavour, storage). Missing capability = classified error, not a silent alternative code path. Fallbacks are hidden behaviour. A skill that pretends to work when the runtime is wrong is exactly the pathology the workspace principle forbids.
WinterTC Common — evidence and recommendation
WinterTC (Ecma TC55, drafting ECMA-429) is the standard-track effort to define a Minimum Common Web API — a curated subset of W3C/WHATWG APIs implementable across server-side runtimes (Node, Deno, Bun, Cloudflare Workers, EdgeRuntime, browser-adjacent). The current snapshot is published at min-common-api.proposal.wintertc.org (ECMA-429); the WinterTC GitHub org shows active drafting (proposal-minimum-common-api); the 12 November 2025 WinterTC meeting minutes confirm ongoing work on the minimum common API, a WinterTC test suite, a Sockets API, and a CLI API. This is standardization-in-progress with cross-runtime buy-in, not a vendor promise.
Target WinterTC Minimum Common API as the tri-runtime portability contract for nexartis-agent-scripts. Any skill using a global outside min-common-api MUST declare runtime-portability: node-only or workers-only in frontmatter; the publish-gate wintertc-check (ast-grep) rule set enforces the declaration. Tri-runtime smoke = Node + Miniflare (Workers) + JSDOM; a skill that passes only in Node without an explicit declaration is a fail-loud gate breach. Final call on adoption occurs at implementation start; the evidence supports moving forward.
- Minimum common web API (ECMA-429 draft)
- Ecma TC55 — scope and charter
- WinterTC55/proposal-minimum-common-api (GitHub)
- WinterTC — work-in-progress (Sockets API, CLI API, test suite)
- W3C WinterTC minutes — 12 November 2025
Proposed architecture — nexartis-agent-scripts
- Layout — _NEXARTIS-SDKs/nexartis-agent-scripts/ — pnpm monorepo. One package per skill. Each package is a self-contained SKILL.md + scripts/ + test/ + references/, publishable independently, discoverable via the workspace-level frontmatter index.
- Skill envelope — SKILL.md with the standard agent-skills spec frontmatter (name, description, when-to-use) EXTENDED with Nexartis-specific fields: runtime-portability (min-common-api tier + tested runtimes), verify (list of validators the skill runs on its own inputs), receipts (whether the skill emits a signed run receipt). Body is progressive-disclosure text.
- Package structure — scripts/ — the executable TS entry points; test/ — vitest suites + tri-runtime smoke; references/ — reference material loaded on demand; package.json exports pinned so publint + attw stay green.
- Discovery — ChunkHound-indexed frontmatter is the discovery layer. Agents query "skills that do X" against the index; the always-loaded slice is name + description only (progressive disclosure); the body loads when the agent chooses to open the skill.
- Publish gate — 5 steps — (1) tsc typecheck. (2) vitest unit + integration. (3) publint + are-the-types-wrong. (4) wintertc-check — an ast-grep rule set that flags any non-min-common-api global usage (process, __dirname, Node-specific fs, etc.) unless the skill declares itself node-only in frontmatter. (5) tri-runtime smoke: Node + Miniflare (Workers) + JSDOM sanity run of the primary entry point.
- scripts:sync — Mirror script that copies published skills to ~/.config/kilo/skills/ so the local Kilo harness sees them without a manual copy step. Idempotent; overwrites are receipts-visible.
Extended frontmatter
Spec fields plus Nexartis extensions. The extensions are the difference between a skill that claims to be portable and a skill that has been proven so.
name(required) — Spec field. Machine-readable skill id (kebab-case).description(required) — Spec field. One-sentence "what this does + when to reach for it". This is the always-loaded discovery text.when-to-use(required) — Spec field. Short bullet list of trigger conditions. Agents pattern-match on this without loading the body.runtime-portability(required) — Nexartis extension. { tier: "min-common-api" | "node-only" | "workers-only"; tested: string[] }. tested lists the runtimes the tri-runtime smoke actually ran against.verify(required) — Nexartis extension. Ordered list of validators the skill runs on its own inputs before executing user-visible work (e.g. ["zod-schema", "wintertc-check"]). Empty is not permitted; if nothing verifies, that is a fail-loud declaration.receipts(optional) — Nexartis extension. If true, the skill emits a signed run receipt on every execution (same receipt store as the harness bandit + moe-search-router receipts). Default false for pure-utility skills that carry no side effects worth logging.
Failure semantics — no hidden behaviour
- Missing runtime capability → classified error naming the missing feature. No silent fallback to a legacy code path.
- Publish gate failure → the package does not publish. There is no "publish anyway with warnings" flag.
- wintertc-check violation without an explicit node-only / workers-only frontmatter declaration → gate fails. The declaration exists so agents can still author intentionally non-portable skills; the gate exists so they cannot do it accidentally.
- scripts:sync overwrite → surfaced in a receipt. The local Kilo harness sees which skills changed and when.
- Tri-runtime smoke divergence (skill passes in Node, fails in Miniflare) → gate fails. The whole point of tri-runtime is that "works in Node" is not evidence.
- Frontmatter drift (indexed description differs from actual) → ChunkHound reindex captures the delta; the discovery layer is only as good as its inputs.
Reference implementation under evaluation — open-ptc-agent
open-ptc-agent (Chen-zexi/open-ptc-agent, ~717★ Python) is the reference open-source implementation of Anthropic Programmatic Tool Calling: universal MCP support, auto-converting any MCP-server tool set into Python functions, progressive tool discovery (tools discovered on-demand instead of upfront-loaded), Daytona-sandboxed execution, multi-LLM (Anthropic + OpenAI + configurable via llms.json). Directly cites the Anthropic engineering posts ("Code execution with MCP", "Introducing advanced tool use") and CodeAct.
- Adopt-vs-bespoke: build nexartis-agent-scripts on top of open-ptc-agent (adopt the runtime; contribute the WinterTC + Nexartis-frontmatter conventions upstream once they are world-class per the workspace fork-and-improve etiquette) OR run bespoke (own the runtime, borrow the paradigm)?
- Does its progressive tool discovery reproduce the published token-reduction numbers on the Nexartis workload and MCP set, or is a re-implementation needed for the ChunkHound-indexed frontmatter discovery loop?
- Sandbox alignment: it uses Daytona; the target here is Cloudflare dynamic workers (sub-second) + Miniflare for the local plane. The porting surface is the sandbox adapter.
- License + provenance review before adoption per workspace etiquette; no upstream issues or feature requests filed without operator approval.
Status: Under evaluation as the candidate conventions vehicle for nexartis-agent-scripts. The workspace convention is research-first: prefer existing packages/collections when they present a clear win; bespoke only when the existing option loses on measured criteria.
The adopt-vs-bespoke decision is recorded in the memory-tooling-decisions log alongside the wider conventions record for this library.
- Chen-zexi/open-ptc-agent
- Anthropic — Code Execution with MCP (paradigm citation)
- Anthropic — Introducing advanced tool use (PTC)
Why a library beats one-off scripts
- Skills grow: Voyager showed the library IS the moat. Ad-hoc scripts inside a session evaporate when the session ends; a curated library compounds across sessions and across agents.
- Publish gate: a one-off script has no gate. A library-managed skill passes typecheck, tests, publint, attw, wintertc-check, and tri-runtime smoke before it can be used. That is the difference between "the agent tried something" and "the agent used a proven capability".
- Discovery: without an indexed frontmatter surface, the agent cannot find the script that already solves the problem. Voyager and CodeAct both depend on retrievability, not just existence.
- Portability: one-off scripts are typically Node-shaped and quietly break in Workers. A library that targets min-common-api by default (with explicit opt-outs) prevents the whole class.
- Receipts: library skills can emit signed run receipts uniformly. Ad-hoc scripts cannot; the observability gap is exactly where trust erodes.
Open questions
- Where does the discovery index live? — ChunkHound over the workspace is the natural default (frontmatter is text), but a dedicated skills index scoped to _NEXARTIS-SDKs/nexartis-agent-scripts/ may pay off if the search router surfaces it as its own expert (see moe-search-router: skill discovery is a candidate expert class).
- How do skills discover each other? — A skill that composes other skills needs a stable inter-skill import contract. Package-level imports work today; a receipt-visible "skill invoked skill" trace is the v0.2 experiment.
- Do we compile skills to a dynamic-worker-loader bundle by default? — Cloudflare Code Mode + Dynamic Worker Loader is the strongest published sub-second sandbox. Bundling every skill for that runtime gives us portability + speed; the cost is a Workers-shaped build step every skill has to pass.
- Verify pairing with the write-strategy rubric — The write-strategies research page (D8) already routes edits by class. Skills that mutate the workspace should route through the same rubric — a skill that touches >3 files should default to weave-patch under the hood. This is a shared-library concern, not per-skill.
- Signed run receipts everywhere — Frontmatter receipts:true toggles the emit. The open question is whether default should flip to true for the whole library once the receipt store handles the volume — the observability upside is large.
Positioning
- Candidate _NEXARTIS-SDKs/ monorepo: nexartis-agent-scripts. First skills mirror the routing rubrics we already codified (search-fanout, write-patch-batch, verify-typecheck-then-test).
- Complements the MoE search-router MCP: skills are a candidate expert class for skill-discovery ("find me a skill that does X"). The router calls the library; the library returns candidate skills with progressive-disclosure metadata.
- Complements the write-strategy rubric (D8): skills that write route through the rubric internally. One place codifies the discipline; skills inherit it.
- Sequencing: v0.1 architecture (this page). v0.2 initial 5–10 skills + publish gate live. v0.3 receipt volume + first bandit-tuned skill selection tied to harness-bandit infrastructure.
How this page stays current
Living architecture paper. Milestones: architecture + literature + one production example (published); first published skills and the publish gate wired up with initial tri-runtime smoke results (next); receipt volume and the first bandit-tuned skill-selection experiments (following).
Sources
- Anthropic — Code Execution with MCP + Programmatic Tool Calling
- Chen-zexi/open-ptc-agent — open-source PTC reference implementation (under evaluation)
- Cloudflare — Code Mode + Dynamic Worker Loader
- Agent Skills — open specification
- Voyager — an open-ended embodied agent with LLMs (arXiv 2305.16291)
- CodeAct — executable code actions elicit better LLM agents (arXiv 2402.01030)
- Hugging Face — smolagents CodeAgent (30% better) blog
- WinterTC Minimum Common API (Ecma TC55 / ECMA-429 draft)
- WinterTC — active work (Sockets API, CLI API, test suite)
- tsdown — Rolldown-backed TypeScript bundler (tsup successor)
- publint — package.json hygiene
- are-the-types-wrong — TS types vs runtime consistency
- MoE Search Router — companion research page
- Write Strategies — companion research page (routing rubric D8)
- Memory Tooling Decisions — decision log