Skip to content
Back to skills

Agent Common

ASecurity

How to use @owlmeans/agent-common — runtime-free contracts for OwlMeans agents: conversation identity, the run-lifecycle flow, the PIPELINE declaration (PipelineSpec, PipelineRun, validatePipelineSpec, orderPipelineSteps, pipelineAncestors), the CUMULATIVE PIPELINE RESULTS contracts (facts, entries, declarations, deterministic renderers) and the record shapes an application persists. Auto-invoked when importing agent record types, a pipeline spec or run type, a cumulative-results type or rend...

  • 3 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 22, 2026
businessgoreactnodetestingbackend

Works with

  • cli

Security analysis

A100/100

Scanned October 6, 2026

npx -y skills add owlmeans/common --skill agent-common --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Agent Common?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Agent Common
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/owlmeans-agent-common/badge)](https://www.skillsdirectory.com/skills/owlmeans-agent-common)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: agent-common
description: "How to use @owlmeans/agent-common — runtime-free contracts for OwlMeans agents: conversation identity, the run-lifecycle flow, the PIPELINE declaration (PipelineSpec, PipelineRun, validatePipelineSpec, orderPipelineSteps, pipelineAncestors), the CUMULATIVE PIPELINE RESULTS contracts (facts, entries, declarations, deterministic renderers) and the record shapes an application persists. Auto-invoked when importing agent record types, a pipeline spec or run type, a cumulative-results type or renderer, conversationFor, truncateAt, or the agent run flow."
user-invocable: false
---

# @owlmeans/agent-common

**Layer:** Cross-cutting domain
**Install:** `"@owlmeans/agent-common": "^0.1.18-rc.48"` in `dependencies`

Serializable contracts for the agent family. No LangChain, no LangGraph, no storage driver — a
backend or a browser bundle imports these to read what an agent wrote without pulling the runtime.
The runtime is `@owlmeans/agent`.

## Key exports

| Export | Description |
|---|---|
| `ConversationRef` | `{ conversationId, scope }` — the thread a run belongs to, and the wider subject it is about. Two fields, because memory is filed per subject while threads may be finer-grained. |
| `conversationFor(purpose, override?)` · `SCOPE_SEP` | Derives a `ConversationRef` from an `LlmPurpose` dedication (`<kind>:<id>`, split on `SCOPE_SEP`); either half is overridable. |
| `truncateAt(text, max)` | Boundary-aware truncation. Every character cap in the family lands here. |
| `agentRunFlow`, `AgentRunStep`, `AgentRunTransition`, `AGENT_RUN_FLOW` | The `@owlmeans/flow` lifecycle a run is driven through. |
| `agentFlows` | Every flow this package declares, for a provider to serve. |
| `ConversationEvent`, `ConversationEventInput` | One finished run, compacted: `summary` + `advice`. |
| `MemoryNode`, `MemoryEvent` (+ `MemoryEventInput`) | Agent-authored memory records. |
| `AgentRunMessage` | What a transport carries — a POINTER (`runId`, `conversationId`, optional `pipeline`/`step`), never state. |
| `PipelineStepSpec`, `PipelineSpec` | The declaration: named steps, `after: string[]` edges, `optional`, `nonIdempotent`, `attempts`, `timeout`. |
| `PipelineRun`, `PipelineRunStatus`, `PipelineProgress` | The persisted run row — `state` is JSON **text** plus `stateChars`; `completed`/`pending`/`warnings`; `heartbeatAt`. |
| `validatePipelineSpec`, `orderPipelineSteps`, `pipelineDescendants`, `pipelineAncestors`, `pipelineAncestry`, `pipelineStep` | Pure spec helpers — no runtime, no graph engine. |
| `CumulativeResultFact`, `CumulativeResultEntry`, `CumulativeResultSource`, `CumulativeFactKind`, `ResultViewMode`, `ResultFactQuery` | CUMULATIVE PIPELINE RESULTS records: one authoritative fact, one step's entry in a ledger. |
| `CumulativeResultsSpec`, `StepResultsSpec`, `ResultSummarySpec`, `mergeResultsSpecs`, `RESULTS_EVERY_STEP` | The JSON-safe declaration — per step: extractors by name, `full`/`omit` consumers, `window`, caps, `refresh`, an optional `summary`. |
| `renderResultEntry`, `renderResultFact`, `renderResultSummary`, `sortFacts`, `factKey`, `compareResultOrder`, `resultLabel`, `rootRunOf` | Deterministic renderers and ledger helpers. |
| `AGENTS_SERVICE` | The service alias — **`agents`**, plural. |
| `AGENT_*_STORE` | Port names a consumer binds its storage under. |
| `AgentRunStatus` | `ok` / `failed`, written on a conversation event. |
| `AgentCommonError`, `AgentRunStateError`, `PipelineSpecError`, `PipelineVersionError`, `PipelineUnknownStepError`, `PipelineNotIdempotentError`, `PipelineStateTooLargeError` | The error family. |
| `DEFAULT_SUMMARY_CHARS` (1200) · `DEFAULT_ADVICE_CHARS` (400) · `DEFAULT_EVENT_WINDOW` (3) · `DEFAULT_MEMORY_NODE_CHARS` (2000) · `DEFAULT_MEMORY_EVENTS_LIMIT` (50) | The caps the runtime's plugins default to. Override them per plugin; read them here rather than restating a number. |
| `DEFAULT_MAX_STATE_CHARS` (256_000) · `DEFAULT_STEP_ATTEMPTS` (1) · `DEFAULT_STEP_TIMEOUT` (30 min) | Pipeline defaults. The state cap is a TRIPWIRE, not a budget. |
| `DEFAULT_RESULTS_MAX_CHARS` (12_000) · `DEFAULT_RESULT_ENTRY_CHARS` (4_000) · `DEFAULT_RESULT_COMPACT_CHARS` (400) · `DEFAULT_RESULTS_WINDOW` (2) · `DEFAULT_RESULT_SUMMARY_CHARS` (600) · `AGENT_CUMULATIVE_RESULT_STORE` | Cumulative-results caps — they bound what a step is TOLD, never what it may produce — and the store's port name. |

## Rules

**Timestamps are ISO strings, never `Date`.** These contracts cross process boundaries and storage
backends and must survive `JSON.stringify` unchanged. A store whose backend prefers dates converts
at its own adapter boundary — that is the adapter's job, not the contract's.

**The service alias is `agents`, and the accessor is `ctx.agents()`.** Plural and deliberately not
`agent`: a consuming application very often already has a service of its own called that, and a
context accessor collision is silent — the second registration simply wins.

**Flow steps are lifecycle stages, not conversational turns, and nothing RESUMES one.** `FlowPayload`
holds flat scalars only and a ReAct loop's turn count is unbounded, so the loop lives inside the
`Working` step and only its counter travels in the payload. What the steps buy is the ability to say
how far a run got when it ended, which is what a plugin reads on `onFinish`. Resumable work is a
PIPELINE — named steps, a state of scalars, side effects guarded per step. A ReAct run is not one:
its state is an unbounded message list whose tool results are already applied to the world.

**A `PipelineSpec` is a DECLARATION and this package holds no engine.** The steps' bodies, the graph,
the checkpointer and the stores all live in `@owlmeans/agent`; what is here is what a browser bundle,
a reconciler or an operator console must read to say where a run stands without importing LangGraph.
That is also why `PipelineRun.state` is JSON **text** with a `stateChars` beside it rather than a
subdocument: a run row crosses a `$jsonSchema`, and a state whose keys are dotted paths does not.

**`validatePipelineSpec` names EVERY fault at once** — unknown `after` targets, cycles, duplicate
step names, `attempts > 1` on a `nonIdempotent` step. A spec is authored once and fixed once, and
reporting faults one per build turns a five-minute edit into five builds.

**A resume across a `version` change is REFUSED, never adapted.** `completed` names steps by string,
so a spec that has since renamed, removed or reordered one would let a resumed run skip work it never
did — silently, because an unknown name in `completed` matches nothing.

**Each working step keeps exactly one non-explicit outgoing transition.** That is what lets
`FlowModel.next()` give a driver an unambiguous answer without knowing the vocabulary. `Fail` is
marked `explicit` precisely so it can never become that automatic answer. Adding a second automatic
edge to any step breaks `next()` for that step.

**Every cap is enforced by truncation after the model answers, never by asking for it.** A cap in a
prompt is a request; a cap in code is a cap. That is why the defaults live here as numbers rather
than as prompt text.

**A conversation id degrades to a named default, never to an empty string.** An empty key would
silently collapse every run of every subject into one thread.

**`pipelineAncestors` mirrors `pipelineDescendants` but excludes the named step.** A re-run re-enters
the step it names; nothing is its own predecessor. `pipelineAncestry` adds each ancestor's DEPTH —
the fewest `after` edges between them — which is what a results window counts, so a direct
predecessor is depth 1 however far apart the two sit in the topological order.

**A rendered entry is deterministic and carries nothing that varies.** Facts sort by kind (file
facts last — a location is what a budget spares first), name and location with a code-unit compare;
no timestamp, run id or revision is ever rendered. Over its cap an entry drops WHOLE facts and says
how many ("they exist: check the files"), never half a signature. An empty non-partial entry renders
to `''` and costs a view nothing; a summary is always labelled "not verified".

**An entry's `order` is a PATH, not a number.** It is the step's topological index behind the index
path of every step it was composed under; where one key prefixes another the longer sorts FIRST, so
a composed run's entries precede the composing step's own. Two pipelines' indexes are not comparable,
which is why a single sequence number cannot order a ledger.

**Declarations merge like skills.** `mergeResultsSpecs` lets later declarations win field by field
but ACCUMULATES extractors, `full` and `omit` lists; `'*'` absorbs names.

**Port names are exported; ports are not bound here.** An unbound port is not an error — the plugin
that needs it degrades to a no-op. `AGENT_PIPELINE_RUN_STORE` is the one exception in spirit: a
pipeline with no run store still runs, but it is not resumable, because the ROW is what a resume
reads. `AGENT_CHECKPOINT_STORE` may be absent with no loss of correctness at all.

## Testing

Category A (unit, no env, no network). This package's own `tests/flow.spec.ts` covers the flow
round-trip — which is also the standing check that `@owlmeans/flow` still works server-side, since
every other consumer of that package is client-side. `tests/results.spec.ts` pins the exact bytes an
entry renders to; a change there changes what every consuming step is told.

## Related

- [[agent]] — the runtime that writes these records
- [[llm-common]] — `LlmPurpose` and `ExecutionState`, which a run's execution is built from
- [[flow]] — the flow model the run lifecycle is declared against

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…