AgentPM™

Agents#

Compose multiple tools behind a single agent manifest.

What is an “agent”?#

An agent is a composition layer: it declares which tools it can call. The agent manifest doesn’t execute code itself. It is a package artifact that enumerates tools (with versions/ranges), prompt examples, and future reserved references so the CLI/SDKs can resolve, install, and expose the tool graph to your agent runtime.

  • Defines capability surface by listing tools the agent may invoke.
  • Drives deterministic installs via agent.lock (package identity + integrity + relationships).
  • Keeps host/runtime lightweight: each tool runs in a managed subprocess with its own dependencies.
  • Preserves future composition metadata for skills, knowledge, memory, and profiles without resolving them yet.

Scaffold an agent#

agentpm init --kind agent --name research-assistant --description "Assistant composed of multiple tools"

Generated skeleton (agent.json):

{
  "kind": "agent",
  "name": "research-assistant",
  "version": "0.1.0",
  "description": "Assistant composed of multiple tools",
  "tools": [],
  "skills": [],
  "knowledge": [],
  "memory": [],
  "profiles": [],
  "examples": [
    {
      "title": "Example prompt",
      "prompt": "Describe the user request this agent should handle."
    }
  ]
}
Note

Add tools to tools[], then run agentpm install to resolve/download artifacts.

Field reference (overview)#

FieldTypeRequiredNotes
$schemastringnoURI to this schema (optional but recommended)
kindenumyes"agent" or "tool" (discriminator)
namestringyes^[a-z][a-z0-9-]{0,63}$
versionsemveryesSemVer string (supports pre/metadata)
descriptionstringyesFree text
toolsarrayyesArray of tool refs: string or {name, version}
skillsarraynoReserved future refs. Validated and preserved, but not resolved today.
knowledgearraynoReserved future refs. Validated and preserved, but not resolved today.
memoryarraynoReserved future refs. Validated and preserved, but not resolved today.
profilesarraynoReserved future refs. Validated and preserved, but not resolved today.
examplesarraynoInline prompt examples { title, prompt }.
readmestringnoPath to README file. Will automatically look for README.md if not specified.
licenseobjectno{ spdx: "license spdx", file: "Path to LICENSE file" }

Declaring tools#

You can reference tools using either a string spec or an object. Both carry the same information; choose one style per team preference.

String spec (concise)#

{
  "tools": [
    "@zack/summarize@0.1.2"
  ]
}

Object form (explicit)#

{
  "tools": [
    { "name": "@zack/summarize", "version": "0.1.2" }
  ]
}

Installing tools for an agent#

Once tools[] is declared, run:

agentpm install
  • Resolves versions.
  • Downloads tool artifacts and prepares them under: .agentpm/tools/<namespace>/<name>/<version>
  • Populates/updates the lockfile agent.lock with package identity, integrity, and dependency relationships.
  • Uses the download cache at .agentpm/cache (use --refresh to bypass).

For a local kind: "agent" manifest, AgentPM does not copy that manifest into .agentpm/agents. The local agent.json remains the source of truth.

You can also add & install in one step:

agentpm install @zack/summarize@0.1.2
# writes/updates tools[] and installs

Direct package install vs manifest-driven install#

AgentPM supports two different install workflows for agents:

Manifest-driven install#

agentpm install
  • reads the local agent.json
  • resolves the local manifest's tools
  • writes a local:agent root into agent.lock
  • installs tools into .agentpm/tools/...
  • does not write the local manifest under .agentpm/agents

Direct package install#

agentpm install @zack/support-agent@0.1.0
  • resolves the requested package by identity
  • if the package is an agent, installs the agent artifact into .agentpm/agents/...
  • reads the installed agent manifest and resolves its tool dependencies
  • installs those tools into .agentpm/tools/...
  • writes an agent:@namespace/name@version root into agent.lock

Lockfile v2 (high level)#

agent.lock v2 records package identity and relationships instead of only a flat tool map.

At a high level it contains:

  • packages
    • keys like tool:@zack/summarize@0.1.2
    • keys like agent:@zack/support-agent@0.1.0
  • roots
    • local:agent for local manifest installs
    • agent:@namespace/name@version for registry-installed agents

That is what lets AgentPM:

  • distinguish manifest-driven local installs from installed registry agents
  • keep multiple versions of the same tool when different agents need different versions
  • expose resolved tool refs from installed agents through the SDKs

Example: two agents, two versions of the same tool#

If:

  • @zack/support-agent@0.1.0 resolves @zack/slack-post-message@0.1.1
  • @zack/escalation-agent@0.1.0 resolves @zack/slack-post-message@0.2.0

then both tool versions can coexist in agent.lock and on disk:

  • .agentpm/tools/zack/slack-post-message/0.1.1/
  • .agentpm/tools/zack/slack-post-message/0.2.0/

Lockfile v2 keeps those package identities separate instead of collapsing them into one flat tool entry.

How agents and tools work together#

  • Your app (Node or Python) uses the SDK to load callable tool functions based on the agent’s tools[].
  • Each tool executes in its own subprocess (correct interpreter/runtime), keeping the host app clean and language-agnostic.
  • The agent manifest + lockfile make the toolset portable and reproducible across dev/CI/prod.

Best practices#

  • Pin for prod: Exact versions in tools[], commit agent.lock.
  • Gate in CI:
agentpm lint --strict
agentpm install --frozen --quiet
  • Name & describe well: Clear name/description helps discovery and registry docs.
  • Evolve safely: Bump the agent’s version when you change its tool set or operational contract.
Dependency scope

Tools are the only resolved dependency type today. skills, knowledge, memory, and profiles are validated and preserved in the manifest and lock metadata, but AgentPM does not resolve or install them yet.