ai-harness — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited ai-harness (Agent Skill) and scored it 96/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 1 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
A bulleted imperative like {match} tells the agent to never reveal, disclose, or mention something to the user. Used adversarially it can instruct the agent to hide its tool calls or lie about what it did — stripping the transparency a user relies on to trust the agent.
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Use this skill for work involving @purista/harness, @purista/harness-openai, or addon packages named @purista/harness-*.
@purista/harness is a standalone, ESM-only agent runtime. It composes typed model aliases, tools, skills, agents, workflows, state, memory, sandboxing, logging, telemetry, and streaming behind one session API.
Keep these layers separate:
defineHarness() registers adapters, defaults, models, tools, skills, agents, and workflowsharness.getSession(id) returns typed session.agents.* and session.workflows.*policy-pack adapters is configured only when needed; ordinary agents do not require policy setup
defineHarness() as the sole construction path. Do not invent standalone defineAgent, defineWorkflow, defineTool, defineSkill, or defineModel helpers.defineHarnessModule<Required>()('module.id', { register }) only for local static composition. Modules contribute normal definitions to the caller's builder; they are not remote plugins, manifests, loaders, or lifecycle owners. Module callbacks cannot build or recursively use a harness.@purista/harness-agent-plugins only for data-only Agent Plugins v1 packages. Require application-owned source/digest/trust approval, inspect diagnostics, then bind selected skills and MCP tools explicitly. A selected stdio server also needs an existing caller-owned data directory and an isolating sandbox implementing both spawn and mountReadOnly; the local host-directory sandbox does not qualify. Never load package code, auto-install dependencies, auto-expose tools, or accept plugin-provided credentials.2026-07-28: use @modelcontextprotocol/client, modern stateless Streamable HTTP, and a spawn-capable sandbox for stdio. Do not add legacy MCP, HTTP+SSE, one-shot exec, or compatibility fallbacks.harness.inspect().modules for content-free provenance..agents(({ agent }) => ({ ... })) and .workflows(({ workflow }) => ({ ... })).ctx.agents.<id>(input) must declare workflow.delegation; prefer delegation.agents allowlists and document budget/model overrides there.ctx.fanOut(...) for ordered, bounded workflow batches. Use ctx.childTasks.start(...) only for workflow-owned isolated background work; task turns queue under the delegation parallel ceiling and never inherit parent history or widen agent permissions.mode: 'continuable' keeps an isolated in-process task conversation open for explicit send(...) turns and close(). Do not use it for durable workflow execution or claim cross-process recovery; use an application queue/worker adapter when work must survive a restart.defaults.historyRetention for durable conversations that need a storage bound. It retains complete newest turns only and requires an atomic StateStore.replaceMessages; maxBytes is serialized UTF-8 storage size, never a token estimate. Use the model's context window/token tooling separately when selecting request context.InvokeOptions.idempotencyKey. Replaying the same successful invocation returns its recorded output without a second provider call or transcript; never derive this key from prompt content.session.release() at the end of an idle request to close live sandbox/MCP resources while preserving StateStore-backed history and runs. session.close() is destructive: it deletes the session record, history, runs, and persisted events.object / object_stream for structured generation. Do not use legacy json capability names.RunEvent values.telemetry({ contentCaptureMode: 'NO_CONTENT' }) is the production default..skills(...), allowlist skill ids per agent, keep read available for skill-backed agents, and verify SKILL.md bodies are not inlined into prompts, logs, traces, or persisted events.ctx.metrics for application-owned counters, histograms, and operation durations inside workflow handlers, custom agent handlers, and TypeScript tool handlers. Do not call the low-level TelemetryShim directly for app metrics..governance(...) afteragents/workflows are declared. Keep simple use cases on per-agent permissions; use governance only for composable/audited policy, approval, or external policy-pack interoperability.
packages/harness/src/harness/defineHarness.ts, models/registry.ts, agents/index.ts, skills/index.ts, ports/*, and provider package source.StateStore, session memory uses MemoryAdapter, and provider context is transient. Bound durable history with whole-turn retention and bound request context with the model's context/token limits.harness.getSession(id), release idle sessions, and shut down the shared harness during process shutdown. Use destructive session close only for explicit conversation deletion.@purista/harness/testing fakes/contracts before live-provider smoke tests.import { z } from 'zod'
import { defineHarness, JsonLogger, inMemorySandbox } from '@purista/harness'
import { openai } from '@purista/harness-openai'
const harness = defineHarness({ name: 'support-ai' })
.logger(new JsonLogger({ level: 'info' }))
.telemetry({ contentCaptureMode: 'NO_CONTENT' })
.sandbox(inMemorySandbox())
.defaults({
historyRetention: { maxTurns: 50, maxBytes: 256_000 }
})
.models({
assistant: {
provider: openai({ apiKey: process.env.OPENAI_API_KEY! }),
model: process.env.OPENAI_MODEL ?? 'gpt-5-mini',
capabilities: ['object', 'tool_use']
}
})
.tools({
lookup_ticket: {
description: 'Look up one support ticket by id.',
input: z.object({ id: z.string() }),
output: z.object({ status: z.string(), summary: z.string() }),
handler: async (_ctx, input) => ({ status: 'open', summary: `Ticket ${input.id}` })
}
})
.agents(({ agent }) => ({
triage: agent({
model: 'assistant',
input: z.object({ ticketId: z.string() }),
output: z.object({ priority: z.enum(['low', 'normal', 'high']), reason: z.string() }),
builtinTools: false,
tools: ['lookup_ticket'],
instructions: 'Use lookup_ticket, then return a validated triage object.'
})
}))
.workflows(({ workflow }) => ({
triage_ticket: workflow({
input: z.object({ ticketId: z.string() }),
output: z.object({ priority: z.string(), reason: z.string() }),
delegation: { agents: ['triage'] },
handler: (ctx) => {
ctx.metrics.counter('support.triage.started', 1)
return ctx.metrics.duration('support.triage.duration', undefined, () => ctx.agents.triage(ctx.input))
}
})
}))
.build()
const session = await harness.getSession('tenant-a:user-42')
const result = await session.workflows.triage_ticket.prompt({ ticketId: 'T-123' })
await session.release()
await harness.shutdown()The example's in-memory state store supports atomic history replacement for local use. Production history retention needs a durable StateStore adapter that implements replaceMessages atomically.
references/configuration.md for package setup, builder order, sessions, state, sandbox, runtime capabilities, streaming, and shutdown.references/model-setup.md for provider aliases, OpenAI setup, defaults, capability-gated model handles, multimodal content, embeddings, and rerank.references/agents-workflows-tools.md for deciding between agents/workflows and wiring typed tools, permissions, MCP, and skill-mounted agents.references/agents-workflows-tools.md also covers optional governance policyand when to prefer it over simple permissions.
references/skills.md for creating harness skill folders and registering/mounting them correctly.references/sandbox.md for in-memory/bash sandboxes, filesystem/exec APIs, snapshots, built-in tool risk, and custom sandbox adapters.references/state-sessions-streaming-errors.md for StateStore, session lifecycle, memory/history, run events, error mapping, and replay.references/durable-feedback-operations.md for durable runtime checkpoints, adapter capabilities, feedback records, readiness, and operational runbooks.references/telemetry-observability.md for OpenTelemetry setup, TelemetryShim, span/metric names, logs, privacy, and adapter context propagation.references/adapters.md for creating and using provider, state store, memory, sandbox, durable runtime, logger, telemetry, tool/MCP, and addon adapter packages.references/testing.md for fake providers, type checks, contract tests, and live-provider boundaries.references/package-surface.md for exports, package boundaries, source files, public docs, and known source-vs-doc checks.This directory is the canonical source for the AI Harness agent skill. Sync a runtime mirror explicitly after changing it, then verify byte-for-byte:
npm run skills:sync -- /path/to/installed/ai-harness
npm run skills:sync -- --check /path/to/installed/ai-harness~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.