Agents#
Compose tools, skills, knowledge, memory, profiles, and an optional loop behind a single agent manifest.
What is an “agent”?#
An agent is a composition layer: it declares which tools, skills, knowledge packages, memory blueprints, instruction profiles, and optional Loop package it can use. The agent manifest doesn’t execute code itself. It is a package artifact that enumerates package dependencies, optional orchestration metadata, and prompt examples so the CLI and SDKs can resolve, install, and expose the graph to your agent runtime.
- Defines capability surface by listing the packages the agent may use.
- 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.
- Treats tools, skills, knowledge, memory, profiles, and loops as first-class resolved package dependencies.
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."
}
]
}Add tools to tools[], skills to skills[], knowledge packages to knowledge[], memory blueprints to memory[], instruction profiles to profiles[], and an optional loop through loop when needed, then run agentpm install to resolve and download artifacts.
Field reference (overview)#
| Field | Type | Required | Notes |
|---|---|---|---|
$schema | string | no | URI to this schema (optional but recommended) |
kind | enum | yes | Must be "agent" |
name | string | yes | ^[a-z][a-z0-9-]{0,63}$ |
version | semver | yes | SemVer string (supports pre/metadata) |
description | string | yes | Free text |
tools | array | yes | Array of tool refs: string or {name, version}; may be empty ([]) |
skills | array | no | Array of skill refs: string or {name, version} |
knowledge | array | no | Array of knowledge refs: string or {name, version} |
memory | array | no | Array of memory refs: string or {name, version} |
profiles | array | no | Array of profile refs: string or {name, version} |
loop | string or object | no | Singular loop ref: string or {name, version} |
bindings | object | no | Optional global, phase, MCP, and consumer-context binding metadata |
examples | array | no | Inline prompt examples { title, prompt }. |
readme | string | no | Path to README file. Will automatically look for README.md if not specified. |
license | object | no | { 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.
The tools field is required for kind: "agent" manifests, even when the agent currently has no tool dependencies and the value is just [].
String spec (concise)#
{
"tools": [
"@zack/summarize@0.1.2"
]
}Object form (explicit)#
{
"tools": [
{ "name": "@zack/summarize", "version": "0.1.2" }
]
}Declaring skills#
Agents may also declare first-class skill dependencies:
{
"skills": [
"@zack/incident-commander@0.1.0",
{ "name": "@zack/slack-incident-update", "version": "^0.1.0" }
]
}Skill dependencies are resolved and locked during install just like tool dependencies.
Declaring knowledge#
Agents may also declare first-class knowledge dependencies:
{
"knowledge": [
"@zack/python-docs@0.1.0",
{ "name": "@zack/support-playbook", "version": "^0.1.0" }
]
}Knowledge dependencies are resolved and locked during install just like tool and skill dependencies.
Declaring memory#
Agents may also declare first-class memory dependencies:
{
"memory": [
"@zack/profile-memory@0.1.0",
{ "name": "@zack/history-memory", "version": "^0.1.0" }
]
}Memory dependencies are resolved and locked during install just like tool, skill, and knowledge dependencies.
Declaring profiles#
Agents may also declare first-class profile dependencies:
{
"profiles": [
"@zack/support-style@0.1.0",
{ "name": "@zack/incident-voice", "version": "^0.1.0" }
]
}Profile dependencies are resolved and locked during install just like tool, skill, knowledge, and memory dependencies.
Declaring a loop#
Agents may declare at most one direct loop dependency:
{
"loop": "@zack/incident-response-loop@1.0.0"
}Object form is also supported:
{
"loop": {
"name": "@zack/incident-response-loop",
"version": "^1.0.0"
}
}Loop dependencies are resolved and locked during install like other first-class package dependencies, but they remain metadata only. Installing a loop does not execute the graph.
Bindings#
Agents may optionally declare authored bindings metadata describing how already-declared package dependencies participate globally, within named loop phases, across named MCP surfaces, or through a consumer-owned context file.
Example:
{
"bindings": {
"consumer_context": {
"file": "runtime/customer-context.json"
},
"global": {
"tools": ["@zack/ticket-reader"],
"knowledge": ["@zack/support-playbook"],
"profiles": ["@zack/support-style"],
"memory": [
{
"package": "@zack/support-customer-state",
"spaces": ["customer_state"]
}
]
},
"phases": {
"respond": {
"skills": ["@zack/support-response-checklist"],
"memory": [
{
"package": "@zack/support-customer-state",
"operations": ["refresh_customer_state"]
}
]
}
},
"mcp": [
{
"id": "support-tools",
"tools": ["@zack/ticket-reader", "@zack/crm-lookup"]
}
]
}
}Binding package identities are versionless by design. Versions remain owned by the top-level dependency fields and agent.lock.
AgentPM validates that bound package identities are declared in the matching top-level dependency collection, but it does not resolve phase names against the installed Loop or validate Memory spaces/operations against Memory Blueprint contents during lint.
Global and phase bindings are additive intent metadata. AgentPM does not calculate or enforce effective runtime availability from them.
Memory bindings#
Memory bindings identify:
- a versionless memory package identity in
package - one or more
spaces - one or more
operations - or both
spacesandoperations
Operations retain their Memory Blueprint-defined triggers and contract semantics. Binding an operation does not redefine when it runs or how it behaves.
MCP bindings#
bindings.mcp names inspectable MCP Tool surfaces:
idtools
It does not define:
- host
- port
- transport
- process execution
- auth
Those runtime concerns belong to the consuming harness or host application.
Consumer context#
bindings.consumer_context.file is:
- author-chosen
- workspace-relative
- optional
- consumer-owned
The file may or may not exist at runtime. AgentPM validates only the safe relative path shape; it does not package or read the file.
Loop access versus bindings#
Loop access metadata and Agent bindings describe different things:
- Loop
accesssays what kind of activity a phase is intended to allow - Agent
bindingssay which installed package identities are meant to participate globally or in a named phase
AgentPM does not reject conflicts between them during lint, publish, or install. A runtime may choose how to interpret that authored metadata later.
Installing tools, skills, knowledge, memory, profiles, and loops for an agent#
Once tools[], skills[], knowledge[], memory[], profiles[], and/or loop are declared, run:
agentpm install- Resolves tool, skill, knowledge, memory, profile, and loop versions.
- Downloads tool artifacts and prepares them under:
.agentpm/tools/<namespace>/<name>/<version> - Downloads skill artifacts and prepares them under:
.agentpm/skills/<namespace>/<name>/<version> - Downloads knowledge artifacts and prepares them under:
.agentpm/knowledge/<namespace>/<name>/<version> - Downloads memory artifacts and prepares them under:
.agentpm/memory/<namespace>/<name>/<version> - Downloads profile artifacts and prepares them under:
.agentpm/profiles/<namespace>/<name>/<version> - Downloads loop artifacts and prepares them under:
.agentpm/loops/<namespace>/<name>/<version> - Populates/updates the lockfile
agent.lockwith package identity, integrity, and dependency relationships. - Uses the download cache at
.agentpm/cache(use--refreshto 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 or updates tools[] for a direct Tool install, then installsagentpm install @zack/incident-commander@0.1.0
# writes or updates skills[] for a direct Skill install, then installsagentpm install @zack/python-docs@0.1.0
# writes or updates knowledge[] for a direct Knowledge install, then installsagentpm install @zack/profile-memory@0.1.0
# writes or updates memory[] for a direct Memory install, then installsagentpm install @zack/support-style@0.1.0
# writes or updates profiles[] for a direct Profile install, then installsagentpm install @zack/incident-response-loop@1.0.0
# writes or updates loop for a direct Loop install, then installsDirect 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,skills,knowledge,memory,profiles, andloop - writes a
local:agentroot intoagent.lock - installs tools into
.agentpm/tools/... - installs skills into
.agentpm/skills/... - installs knowledge into
.agentpm/knowledge/... - installs memory into
.agentpm/memory/... - installs profiles into
.agentpm/profiles/... - installs loops into
.agentpm/loops/... - 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, skill, knowledge, memory, profile, and loop dependencies
- installs those tools into
.agentpm/tools/... - installs those skills into
.agentpm/skills/... - installs those knowledge packages into
.agentpm/knowledge/... - installs those memory packages into
.agentpm/memory/... - installs those profile packages into
.agentpm/profiles/... - installs that loop package into
.agentpm/loops/... - writes an
agent:@namespace/name@versionroot intoagent.lock
Lockfile (high level)#
agent.lock records package identity and relationships instead of only a flat tool map.
Skill-containing graphs are written as lockfile_version: 3.
At a high level it contains:
packages- keys like
tool:@zack/summarize@0.1.2 - keys like
skill:@zack/incident-commander@0.1.0 - keys like
knowledge:@zack/python-docs@0.1.0 - keys like
memory:@zack/profile-memory@0.1.0 - keys like
profile:@zack/support-style@0.1.0 - keys like
loop:@zack/incident-response-loop@1.0.0 - keys like
agent:@zack/support-agent@0.1.0
- keys like
rootslocal:agentfor local manifest installsagent:@namespace/name@versionfor 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.0resolves@zack/slack-post-message@0.1.1@zack/escalation-agent@0.1.0resolves@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/
Modern lockfiles keep 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[], commitagent.lock. - Gate in CI:
agentpm lint --strict
agentpm install --frozen --quiet- Name & describe well: Clear
name/descriptionhelps discovery and registry docs. - Evolve safely: Bump the agent’s
versionwhen you change its tool set or operational contract.
Agents resolve tools[], skills[], knowledge[], memory[], profiles[], and optional singular loop. Bindings are preserved as authored metadata only.