Skip to main content

PersonaSpec toolkit for LLM agents

Project description

larva

larva is the PersonaSpec toolkit for the opifex stack. It validates, normalizes, registers, resolves, updates, exports, and projects persona specs.

Status: this document describes the implemented registry-local variants surface. Assembly/component public surfaces have been removed.

The canonical PersonaSpec contract authority is ../opifex. larva consumes that contract; it does not redefine it.

What larva is for

Use larva when you want a stable authority for agent persona definitions instead of ad hoc prompt files scattered across tools and repos.

  • Validate PersonaSpec JSON before it reaches runtime
  • Store canonical personas in a local registry under ~/.larva/
  • Manage registry-local variants without changing the PersonaSpec schema
  • Resolve, clone, update, delete, and export personas across tools
  • Project the active variant of each registered persona into OpenCode
  • Expose the same operations through MCP, CLI, Python, and a small web UI

larva does not run agents, call LLMs, enforce gateway policy, or manage memory. larva opencode is only a launcher for the real OpenCode runtime.

Install

pip install larva

Development checkout:

uv sync
uv run larva --help

Quick start

Create a complete PersonaSpec JSON file:

{
  "spec_version": "0.1.0",
  "id": "code-reviewer",
  "description": "Reviews code changes with read-focused tooling.",
  "prompt": "You are a senior code reviewer.",
  "model": "openai/gpt-5.5",
  "capabilities": {"shell": "read_only"}
}

Then validate, register, and resolve:

larva validate code-reviewer.json
larva register code-reviewer.json
larva resolve code-reviewer --json

Core concepts

PersonaSpec

The main larva artifact is a flat JSON object called PersonaSpec.

Key rules:

  • id is required and must be flat kebab-case
  • prompt is opaque executable text; larva stores and validates it as text and does not parse placeholders or infer runtime behavior from it
  • spec_version is schema identity, not persona revisioning
  • v1 pins spec_version to "0.1.0"
  • spec_digest is recomputed by larva from canonical content
  • there is no inheritance, base:, or variant field in canonical output

Registry-local variants

Variants are local registry metadata, not PersonaSpec fields. They let one base persona id have multiple stored configurations while agent-facing list/resolve surfaces keep the base id stable.

~/.larva/
  registry/
    code-reviewer/
      manifest.json          # {"active": "default"}
      variants/
        default.json         # PersonaSpec with id == "code-reviewer"
        tacit.json           # PersonaSpec with id == "code-reviewer"

Important behavior:

  • larva list shows base persona ids, not variant metadata
  • larva resolve code-reviewer returns the active variant as a canonical PersonaSpec
  • larva resolve code-reviewer --variant tacit returns a specific variant
  • variant is passed as an operation parameter or registry envelope metadata; it is never accepted inside a PersonaSpec object
  • manifest.json stores only the active pointer ({"active": "default"}); missing or corrupt manifests fail closed instead of being auto-created
  • assembly/component inputs are removed; register full canonical PersonaSpecs directly

Interfaces

MCP

larva_validate(spec)                    -> ValidationReport
larva_register(spec, variant?)          -> {id, registered}
larva_resolve(id, overrides?, variant?) -> PersonaSpec
larva_list()                            -> [{id, description, spec_digest, model}]
larva_update(id, patches, variant?)     -> PersonaSpec
larva_update_batch(where, patches, dry_run?) -> {items, matched, updated}
larva_clone(source_id, new_id)          -> PersonaSpec
larva_delete(id)                        -> {id, deleted}
larva_clear(confirm)                    -> {cleared, count}
larva_export(all?, ids?)                -> [PersonaSpec, ...]
larva_variant_list(id)                  -> registry variant metadata
larva_variant_activate(id, variant)     -> {id, active}
larva_variant_delete(id, variant)       -> {id, variant, deleted}

Removed MCP tools:

larva_assemble
larva_component_list
larva_component_show

Start larva as an MCP server:

larva mcp

CLI

larva validate <spec.json> [--json]
larva register <spec.json> [--variant <name>] [--json]
larva resolve <id> [--variant <name>] [--override key=value]... [--json]
larva list [--json]
larva update <id> [--variant <name>] --set key=value [--set ...] [--json]
larva clone <source-id> <new-id> [--json]
larva delete <id> [--json]
larva clear --confirm "CLEAR REGISTRY" [--json]
larva export --all [--json]
larva export --id <id> [--id <id>]... [--json]
larva variant list <id> [--json]
larva variant activate <id> <variant> [--json]
larva variant delete <id> <variant> [--json]
larva doctor [--json]
larva opencode [OPENCODE_ARG ...]

Python API

from larva.shell.python_api import (
    validate,
    register,
    resolve,
    update,
    variant_list,
    variant_activate,
    variant_delete,
)

Web UI

larva serve

The packaged web UI shows base persona ids and active variant state for human management. Registry variant endpoints return {_registry, spec} envelopes; _registry is local metadata and spec is canonical PersonaSpec.

OpenCode plugin

larva opencode
larva opencode --agent python-senior

larva opencode launches the real OpenCode CLI with a temporary dynamic config built from the active variant of each base persona id in the larva registry. The OpenCode agent name is the Larva base persona id; inactive registry-local variants are not projected as separate OpenCode agents.

The wrapper/plugin path uses placeholder agents at startup and replaces each [larva:<id>] placeholder inside OpenCode's system-prompt transform before a model request. This gives persona prompts system-prompt strength rather than ordinary MCP/tool-result context.

The hardening contract for this path is: existing persona ids refresh by re-resolving the selected id, cache is performance-only, raw placeholders must never reach the model, and no /larva refresh command is required. Adding or deleting persona ids still requires restarting larva opencode so OpenCode can see the new agent list. See contrib/opencode-plugin/README.md for current behavior, target refresh semantics, and failure handling.

Architecture

larva uses a strict layered structure enforced by Invar.

Layer Path Role
Core src/larva/core/ Pure logic, contracts, no I/O
App src/larva/app/ Use-case orchestration
Shell src/larva/shell/ CLI, MCP, filesystem, web adapters

Read next

  • docs/README.md - documentation map by category
  • docs/guides/USER_GUIDE.md - detailed human-oriented usage guide
  • docs/guides/USAGE.md - agent-oriented operational guide
  • docs/reference/INTERFACES.md - public interface specification
  • docs/reference/ARCHITECTURE.md - module boundaries and dependency design
  • design/registry-local-variants-and-assembly-removal.md - accepted design for variant routing and assembly removal
  • docs/adr/ADR-001-spec-version-boundary.md - spec_version design decision
  • docs/adr/ADR-002-capability-intent-without-runtime-policy.md - capability intent model
  • docs/adr/ADR-003-canonical-requiredness-authority.md - canonical requiredness authority
  • docs/adr/ADR-004-empty-capabilities-and-unrestricted-semantics.md - empty capability semantics and unrestricted boundary

License

AGPL-3.0-or-later

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

larva-0.4.9.tar.gz (929.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

larva-0.4.9-py3-none-any.whl (109.1 kB view details)

Uploaded Python 3

File details

Details for the file larva-0.4.9.tar.gz.

File metadata

  • Download URL: larva-0.4.9.tar.gz
  • Upload date:
  • Size: 929.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for larva-0.4.9.tar.gz
Algorithm Hash digest
SHA256 8c4a7e5ffef921829bd821e0c777f0a614a727e701c829a6ad6e6f4a1906e66d
MD5 48b108f1be687d1b36bb698db7d88450
BLAKE2b-256 8be1c3e2670ed7a2a2b2e2596f27b4ab31276e8290cee8390019c439dc0a54d3

See more details on using hashes here.

Provenance

The following attestation bundles were made for larva-0.4.9.tar.gz:

Publisher: publish.yml on Tefx/larva

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file larva-0.4.9-py3-none-any.whl.

File metadata

  • Download URL: larva-0.4.9-py3-none-any.whl
  • Upload date:
  • Size: 109.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for larva-0.4.9-py3-none-any.whl
Algorithm Hash digest
SHA256 6d1a6ce6de4783bd0619b7fa71681074c18c34af1b7fde969cf6774ae779f9ba
MD5 aed6198a7356f9f779f888b3b967aa67
BLAKE2b-256 cdf007b74815470686aba17e3f7e665ca5489de0c28c6fefed85bc68ee53d091

See more details on using hashes here.

Provenance

The following attestation bundles were made for larva-0.4.9-py3-none-any.whl:

Publisher: publish.yml on Tefx/larva

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page