Trust-restricting inheritance and runtime resolver for AI agent manifests. Multi-runtime: Claude, Gemini, Codex, Ollama, and more. (Import as `agentspec`.)
Project description
AgentSpec
Trust-restricting inheritance for agent manifests. A resolver turns them into a runnable CLI invocation.
Existing agent formats (gitagent, Agent Format, OSSA, Open Agent Spec) are static config files. AgentSpec is two things neither of them does:
- A trust model. Agent manifests inherit from other manifests, and a child can only narrow the parent's trust — never widen it. The merger enforces the invariant across three dimensions (filesystem, network, exec) at parse time, so no downstream code path can accidentally elevate a child past its parent's permissions.
- A resolver. Given a manifest and the state of your machine (CLIs installed, API keys in env, models available), it picks the concrete runtime + flags that will actually run. If the environment is short of what the manifest needs, it tells you what's missing instead of failing mid-execution.
# parent.agent
trust:
filesystem: readwrite
network: allow
exec: allow
# child.agent
inherits: parent
trust:
filesystem: readonly # narrowed — OK
network: deny # narrowed — OK
exec: allow # inherited
After merge, the child has {readonly, deny, allow}. If it had tried to widen any dimension (e.g. filesystem: readwrite in the child), the merger rejects the manifest at load time.
your .agent file
↓
resolver + trust-restricting merger ← the defensible bits
↓
claude-code / gemini-cli / codex-cli / aider / opencode / ollama
Extensions (optional, not the pitch)
- Agent profiles. Persist what an agent has done across sprints. Ed25519-signed so tampering is detectable. Signing proves who signed the bytes — not that the claimed work actually happened. Currently alpha; don't deploy without reading SECURITY.md.
- Gym. Test harness for running agents against task fixtures and corpora.
- Noether composition. Optional integration for pipelines built on Noether.
Why AgentSpec
"I have this agent definition. Don't let a child widen trust beyond its parent. Figure out what CLI is installed, what API keys I have, pick the best runtime, warn me about what's missing, and just run it."
| Feature | AgentSpec | Others |
|---|---|---|
| Trust-restricting inheritance (merger enforces invariant) | ✓ | ✗ |
| Resolver (auto-negotiate runtime) | ✓ | ✗ |
| Content-addressable hashing | ✓ | partial |
| Multi-runtime (6 frameworks) | ✓ | usually 1 |
| ACLI-compliant CLI for agent discovery | ✓ | ✗ |
Install
pip install agentspec-alpibru
PyNaCl ships as a core dep — signing works out of the box. Optional extras:
pip install "agentspec-alpibru[registry]" # FastAPI registry server
# (The package is published as agentspec-alpibru on PyPI.
# In code, you still import it as `agentspec`.)
Quick Start
# Create a new agent
agentspec init my-researcher
# Validate the schema
agentspec validate my-researcher.agent
# See what would run (without executing)
agentspec resolve my-researcher.agent
# Run it
agentspec run my-researcher.agent --input "quantum tunneling"
# Push to a registry
agentspec push my-researcher.agent --registry https://registry.agentspec.dev
# Pull and run someone else's agent
agentspec pull ag1:abc123 --registry https://registry.agentspec.dev
The .agent Format
apiVersion: agent/v1
name: deep-researcher
version: 1.0.0
# What model + capability tier
model:
capability: reasoning-high
preferred:
- claude/claude-sonnet-4-6
- gemini/gemini-2.5-pro
- local/llama3:70b
# Abstract skills (resolver maps to concrete tools)
skills:
- web-search
- cite-sources
# Behavior traits (portable across models)
behavior:
traits:
- cite-everything
- never-guess
temperature: 0.2
# Trust invariant — child cannot escalate
trust:
filesystem: none
network: allowed
exec: none
Two formats supported:
- Single file (
researcher.agent) — simple, hashable - Directory (
researcher/) — rich identity withagent.yaml+SOUL.md+RULES.md
Inheritance
Agents extend other agents with enforced merge semantics:
base: ./researcher.agent
merge:
skills: append # append | override | restrict
tools: append
behavior: override
trust: restrict # always restrict — child cannot escalate
The trust: restrict invariant is hardcoded. A child agent can never escalate permissions beyond its parent. Enforced at merge time.
The Resolver
Given a .agent file, the resolver:
- Detects installed runtimes (
shutil.which("claude"), etc.) - Checks API keys in environment
- Walks the model preference list, picks the first that's available
- Maps abstract skills to concrete tools
- Builds the system prompt from traits / SOUL.md / RULES.md
- Falls back to capability tier if no preferred model resolves
- Explains every decision with
--verbose
$ agentspec resolve researcher.agent
Runtime: claude-code
Model: claude/claude-sonnet-4-6
Auth: env.ANTHROPIC_API_KEY
Tools: web-search, cite-sources
Resolver decisions:
Detected runtimes: [claude-code, gemini-cli, ollama]
selected claude/claude-sonnet-4-6 via claude-code (env.ANTHROPIC_API_KEY)
skill web-search: resolved to brave-mcp
skill cite-sources: resolved to arxiv-mcp
Agent Profiles & Signed Portfolios
Extension (alpha). Persistent signed agent identity that accumulates across sprints. Useful if you want agents that carry history, but not required for the basic manifest → resolve → run path. Don't deploy without reading SECURITY.md.
from agentspec.profile import ProfileManager
from agentspec import load_agent
mgr = ProfileManager("./profiles")
manifest = load_agent("my-agent.agent")
profile = mgr.load_or_create(manifest)
# After a sprint completes
mgr.process_retro(profile, feedback={
"assessment": "completed",
"blockers": ["pandas std=0 silently skips z-score"],
"tools": ["pandas", "fastapi", "pytest"],
"clarity": 9,
}, sprint_id="sprint-42", project="OTA Anomaly Detector")
# Profile now has:
# - signed memories (Ed25519)
# - portfolio entry
# - skill proofs (pandas at 70% confidence)
# - all verifiable against supervisor pubkey
Cold start: profiles seed from the manifest (declared skills at 30%). After real sprints, demonstrated skills upgrade to 70%+.
This means agents are portable with their experience. Pull an agent from the registry and you get not just its config but its accumulated knowledge — signed, verifiable, content-addressed.
ACLI Compliant
Built with ACLI — agents discover capabilities at runtime:
agentspec introspect # full command tree as JSON
agentspec skill # generate SKILLS.md
agentspec --help # structured help
CLI Commands
Core:
| Command | Description |
|---|---|
init |
Scaffold a new .agent project |
validate |
Validate a .agent file against the schema |
resolve |
Show what would run without executing |
run |
Resolve and execute an agent |
extend |
Scaffold a child agent extending an existing one |
push |
Publish an agent to a registry |
pull |
Fetch an agent from a registry |
Extras:
| Command | Description |
|---|---|
search |
Semantic search for agents in a remote registry |
schema |
Print the JSON Schema for .agent files |
gym run |
Run an agent against task fixtures / corpora |
records list / show / verify |
Inspect and verify signed execution records |
introspect |
ACLI command tree as JSON (for agent discovery) |
Runtime isolation
agentspec run wraps the spawned CLI in bwrap (bubblewrap) when it's available on PATH, deriving a sandbox policy from the manifest's trust block. Fresh namespaces, cap-drop, workdir-only RW by default; network is gated by trust.network.
agentspec run my.agent # --via=auto: use bwrap if installed
agentspec run my.agent --via=bwrap # require bwrap; fail if missing
agentspec run my.agent --via=none --unsafe-no-isolation # explicit opt-out
export AGENTSPEC_ISOLATION=none # env fallback
A manifest with non-trivial trust (anything other than {full, allowed, full}) fails when bwrap is missing — no silent downgrade. Permissive manifests still run unsandboxed with a warning. See SECURITY.md for the full threat model and docs/proposals/002-trust-enforcement-via-noether.md for the design.
Noether Integration
Extension (optional). AgentSpec operations are registered as Noether stages (validate, resolve, hash, merge, profile_*, etc.) so they can compose with other stages and be served as HTTP APIs via noether serve. Not required for the core workflow — see the Noether docs if you want the pipeline story.
Registry
Push and pull agents from any Noether-compatible registry. Alpha — read SECURITY.md before exposing publicly.
Multi-tenant auth (recommended for anything shared):
export AGENTSPEC_API_KEYS="alice:alice-secret,bob:bob-secret"
Each tenant gets isolated storage — alice cannot pull, list, or delete bob's manifests. Anonymous reads still see the aggregated public catalog across all tenants. For legacy single-key setups, AGENTSPEC_API_KEY=secret still works and maps to the tenant default.
# Self-hosted (docker compose up in noether-cloud)
agentspec push my.agent --registry http://localhost:3000
# Public registry
agentspec push my.agent --registry https://registry.agentspec.dev
agentspec search "researcher" --registry https://registry.agentspec.dev
agentspec pull <id> --registry https://registry.agentspec.dev
If the agent has a signed profile, it's stored alongside the manifest — so pulling can optionally bring the accumulated history too.
Base Agent Templates
Pre-built bases in examples/bases/ for the 4 main runtimes, each with a Noether-flavored variant:
bases/
claude.agent → claude-noether.agent
gemini.agent → gemini-noether.agent
codex.agent → codex-noether.agent
local.agent → local-noether.agent
Extend them in your own agents:
base: bases/claude-noether.agent
merge:
skills: append
behavior:
traits:
- my-custom-trait
Architecture
src/agentspec/
parser/ Pydantic models, .agent loader, content-addressable hashing [core]
resolver/ Environment negotiation, inheritance, merge engine [core]
runner/ Spawns the resolved runtime [core]
registry/ HTTP client + FastAPI server for manifest push/pull [core]
cli/ ACLI-compliant CLI (Typer + acli-spec) [core]
profile/ Persistent identity, memories, portfolio, Ed25519 signing [extension]
gym/ Test harness for agents against task fixtures / corpora [extension]
Testing
pytest tests/ # 271 tests — parser, merger, resolver, provisioner,
# profile, signing (Ed25519 round-trip/tamper/wrong-key),
# registry auth, runner, multi-CLI parity
License
EUPL-1.2 — the European Union Public Licence. Compatible with most other open source licenses (GPL, MIT, Apache via the matrix in the EUPL).
Documentation
Full documentation: agentspec.dev
Or build locally:
pip install "agentspec-alpibru[docs]"
mkdocs serve
Contributing
This is part of a larger ecosystem:
- agentspec — this repo
- noether — Noether composition engine
- noether-cloud — registry + enterprise infra
- caloron-noether — autonomous sprint orchestrator (uses AgentSpec for agent definitions)
- acli — agent-friendly CLI standard
Project status
One active maintainer, best-effort response times. Core (parser + resolver + trust-restricting merger) is stable and tested. Profile signing is stable since 0.4.1. The registry, portfolio profiles, and Noether integration are alpha — see SECURITY.md before deploying. Not suitable for deployments requiring vendor SLAs.
The package currently ships as agentspec-alpibru on PyPI. The -alpibru suffix is historical; a rename (with a deprecated alias) is on the roadmap.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agentspec_alpibru-0.5.0.tar.gz.
File metadata
- Download URL: agentspec_alpibru-0.5.0.tar.gz
- Upload date:
- Size: 89.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d4c2e96e96960c77e052aef1ca456ace773e51dc61d0f09e8ebd2cb3c86943e6
|
|
| MD5 |
a06ed9a0160779c8a27101085f71770b
|
|
| BLAKE2b-256 |
e842d671c85f5d9501373c5d47c0890a5383138f52c67d8b475a23ac8146646a
|
Provenance
The following attestation bundles were made for agentspec_alpibru-0.5.0.tar.gz:
Publisher:
release.yml on alpibrusl/agentspec
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agentspec_alpibru-0.5.0.tar.gz -
Subject digest:
d4c2e96e96960c77e052aef1ca456ace773e51dc61d0f09e8ebd2cb3c86943e6 - Sigstore transparency entry: 1340771229
- Sigstore integration time:
-
Permalink:
alpibrusl/agentspec@cfd7635c1aca49d9fe834e1a6989d708a2c33280 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/alpibrusl
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@cfd7635c1aca49d9fe834e1a6989d708a2c33280 -
Trigger Event:
push
-
Statement type:
File details
Details for the file agentspec_alpibru-0.5.0-py3-none-any.whl.
File metadata
- Download URL: agentspec_alpibru-0.5.0-py3-none-any.whl
- Upload date:
- Size: 87.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
da94e3f975fb6d44d20be7f3f62959f7f9851ec9ed93bd4dfad84b33effd92fe
|
|
| MD5 |
1725d7926ec5c8972f1ce5baee6b1add
|
|
| BLAKE2b-256 |
af93574a4c5d98153218cad13657ae7468a9754d97cc621e27546cb9f72582eb
|
Provenance
The following attestation bundles were made for agentspec_alpibru-0.5.0-py3-none-any.whl:
Publisher:
release.yml on alpibrusl/agentspec
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agentspec_alpibru-0.5.0-py3-none-any.whl -
Subject digest:
da94e3f975fb6d44d20be7f3f62959f7f9851ec9ed93bd4dfad84b33effd92fe - Sigstore transparency entry: 1340771241
- Sigstore integration time:
-
Permalink:
alpibrusl/agentspec@cfd7635c1aca49d9fe834e1a6989d708a2c33280 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/alpibrusl
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@cfd7635c1aca49d9fe834e1a6989d708a2c33280 -
Trigger Event:
push
-
Statement type: