universal-agent
v2.2.1
Published
Universal AI agent packaging format — bundle souls, memories, skills, tools, crons, subagents, and encrypted secrets into a single portable archive, then compile to any platform.
Maintainers
Readme
agentpkg
One format for all your AI agents. Write your agent once, then compile it to Claude Code, Cursor, Copilot, Windsurf, CrewAI, OpenAI, or APM.
agentpkg pack ./my-agent
agentpkg compile agent.agentpkg.zip --target claude-codeThe Problem
AI agents are locked into whatever platform built them. Your Claude Code agent can't move to Cursor. Your Cursor rules don't work in Copilot. Your CrewAI agents can't become Windsurf rules.
agentpkg solves this. You define your agent once (its personality, memories, skills, tools, secrets, everything) and agentpkg compiles it into the exact file structure each platform expects.
Install
npm install -g universal-agentNeeds Node.js 18+. Zero runtime dependencies. The CLI command is still agentpkg.
Tutorial: Your First Agent in 5 Minutes
Step 1: Create a new agent
agentpkg init my-agentThis creates a my-agent.agentpkg/ folder with a starter template.
Step 2: Customize your agent
Open my-agent.agentpkg/soul/system-prompt.md and write your agent's personality:
You are a friendly code reviewer. You focus on readability and always
explain your suggestions. You never nitpick formatting.Open my-agent.agentpkg/soul/identity.json to set the model:
{
"model": "claude-sonnet-4-20250514",
"temperature": 0.3
}Step 3: Add some memories
Create a file like my-agent.agentpkg/memories/entries/pref-001.json:
{
"id": "pref-001",
"content": "User prefers TypeScript over JavaScript",
"type": "preference",
"importance": 0.9
}Step 4: Pack it up
agentpkg pack my-agent.agentpkgThis creates my-agent.agentpkg.zip, a single portable file you can share, back up, or compile.
Step 5: Compile to any platform
# Just Claude Code
agentpkg compile my-agent.agentpkg.zip --target claude-code -o ./output
# Or all platforms at once
agentpkg compile my-agent.agentpkg.zip --target all -o ./outputThat's it. Your ./output folder now has the real native files each platform expects.
Tutorial: Build an Agent Interactively
If you don't want to edit files by hand, use the interactive builder:
agentpkg createIt walks you through everything: name, description, system prompt, model, temperature, rules, memories, and skills. Just answer the questions and your agent is ready.
You can also add things to an existing agent anytime:
agentpkg add memory my-agent.agentpkg # teach it something new
agentpkg add skill my-agent.agentpkg # give it a new ability
agentpkg add rule my-agent.agentpkg # add a guardrail
agentpkg add secret my-agent.agentpkg # add an API key
agentpkg add cron my-agent.agentpkg # schedule a task
agentpkg add tool my-agent.agentpkg # define a toolOr update existing settings:
agentpkg set soul my-agent.agentpkg # rewrite the personality
agentpkg set model my-agent.agentpkg # switch to a different model
agentpkg set description my-agent.agentpkgThen pack and compile as usual:
agentpkg pack my-agent.agentpkg
agentpkg compile my-agent.agentpkg.zip --target all -o ./outputTutorial: Using the Library in Code
If you want to build agents programmatically:
import { AgentPackage } from "universal-agent";
import { compile } from "universal-agent/compile";
// Create your agent
const agent = new AgentPackage({
name: "Research Assistant",
description: "Helps find and summarize ML papers",
});
// Give it a personality
agent.setSoul(
"You are an AI research assistant specializing in ML papers. Always cite sources.",
{ model: "claude-sonnet-4-20250514", temperature: 0.3 },
{ rules: ["Always cite sources", "Prefer recent papers"], refusals: [], safetyNotes: [] }
);
// Teach it things
agent.addMemory({ id: "m1", content: "User studies RLHF", type: "preference", importance: 0.9 });
// Give it skills
agent.addSkill({ name: "arxiv-search", description: "Search arxiv for papers", instructions: "# How to search\n..." });
// Give it tools
agent.addTool({ name: "search", description: "Search knowledge base", parameters: { type: "object" } });
// Schedule recurring work
agent.addCron({ name: "daily-digest", schedule: "0 8 * * *", action: "Compile daily paper digest" });
// Connect to services
agent.addIntegration({ name: "slack", type: "mcp", url: "https://slack.mcp.example.com/sse" });
// Add secrets (encrypted when packed)
agent.addSecret({ key: "SLACK_TOKEN", value: "xoxb-...", type: "token", integration: "slack" });
// Add a helper agent
const helper = new AgentPackage({ name: "citation-bot" });
helper.setSoul("Format citations in BibTeX, APA, or MLA.");
agent.addSubagent(helper);
// Pack with encrypted secrets
await agent.pack("research-assistant.agentpkg.zip", "my-passphrase");
// Or compile directly
compile(agent, "claude-code", "./output");
compile(agent, "crewai", "./output");
compile(agent, "copilot", "./output");Tutorial: Working with Secrets
Secrets (API keys, tokens, passwords) are encrypted with AES-256-GCM before they touch disk. Without the passphrase, the vault is unreadable.
Packing with secrets
Put your secrets in the secrets/ folder (one file per secret, filename = key, contents = value), then pack with a passphrase:
agentpkg pack ./my-agent --passphrase "strong-passphrase-here"Inspecting without decrypting
You can see which secrets are in a package without the passphrase:
agentpkg inspect agent.agentpkg.zip
# Shows: 3 secrets (encrypted)
# SLACK_BOT_TOKEN
# OPENAI_API_KEY
# DATABASE_URLCompiling with secrets
When you compile, pass the passphrase and secrets get injected into the right place for each platform:
agentpkg compile agent.zip --target claude-code --passphrase "strong-passphrase-here"| Platform | Where secrets end up |
|---|---|
| Claude Code | .env file and .mcp.json env fields |
| CrewAI | .env (environment variables) |
| OpenAI | .env and config metadata |
| Others | .env file |
Passphrase tips
agentpkg requires at least 8 characters but will warn you if your passphrase is weak. For real security, use 12+ characters with a mix of letters, numbers, and symbols.
What's Inside a Package
my-agent.agentpkg/
├── manifest.json # Package metadata
├── soul/
│ ├── system-prompt.md # The agent's personality
│ ├── identity.json # Model config (model, temperature, etc.)
│ └── guardrails.json # Rules and boundaries
├── memories/
│ ├── index.json
│ └── entries/*.json # Things the agent remembers
├── skills/
│ └── skill-name/
│ ├── skill.json # Skill metadata
│ ├── SKILL.md # Skill instructions
│ └── handler.js # Optional code
├── tools/
│ └── tool-name/
│ └── tool.json # Tool schema and parameters
├── crons/
│ └── schedules.json # Scheduled tasks
├── subagents/
│ └── helper.agentpkg/ # Nested agent packages
├── workflows/
│ └── deploy.json # Multi-step workflows
├── integrations/
│ └── connections.json # MCP servers, APIs, webhooks
├── knowledge/
│ ├── documents/*.md # Reference docs
│ └── structured/*.json # Structured data
├── secrets/
│ └── vault.json # Encrypted credentials
└── meta/
└── platform-raw/ # Original platform export (for lossless round trips)Compile Targets
Each target produces the platform's actual native file structure:
| Target | Flag | What you get |
|---|---|---|
| Claude Code | --target claude-code | CLAUDE.md, .claude/ with settings, skills, agents, rules, plus .mcp.json |
| Cursor | --target cursor | .cursor/rules/*.mdc with proper frontmatter, plus AGENTS.md |
| GitHub Copilot | --target copilot | .github/copilot-instructions.md, agents, skills, prompts, plus AGENTS.md |
| Windsurf | --target windsurf | .windsurf/rules/*.md, .windsurfrules, plus AGENTS.md |
| CrewAI | --target crewai | Full Python project with pyproject.toml, agents.yaml, tasks.yaml, crew.py, tools |
| OpenAI | --target openai | openai-responses-config.json (Responses API) and openai-assistant-config.json |
| Microsoft APM | --target apm | apm.yml, .apm/ directory, AGENTS.md, CLAUDE.md |
Tutorial: Import from Any Platform
The import command reads a platform's native directory and converts it to an agentpkg package. It auto-detects which platform you're importing from.
# Just point it at a directory. It figures out the rest.
agentpkg import ~/.config/openclaw
agentpkg import ./my-cursor-project
agentpkg import ./my-repoWhat it detects
| Platform | How it's recognized |
|---|---|
| OpenClaw | openclaw.json or workspace/SOUL.md |
| Claude Code | CLAUDE.md or .claude/ directory |
| Cursor | .cursor/ or .cursorrules |
| GitHub Copilot | .github/copilot-instructions.md |
| Windsurf | .windsurf/ or .windsurfrules |
| CrewAI | pyproject.toml with crewai dependency |
| APM | apm.yml or .apm/ directory |
What it imports
Each importer reads the platform's native files:
- System prompt from wherever the platform stores it (CLAUDE.md, .cursorrules, copilot-instructions.md, etc.)
- Rules and guardrails from rule directories (.claude/rules/, .cursor/rules/, .windsurf/rules/)
- Skills from skill directories
- Subagents from agent directories (.claude/agents/, .github/agents/)
- MCP integrations from .mcp.json
- Secrets (when you pass
--include-secrets)
Examples
# Import OpenClaw with secrets
agentpkg import ~/.config/openclaw --include-secrets --passphrase "my-key"
# Import a Cursor project
agentpkg import ./cursor-project -o my-agent.agentpkg.zip
# Force a specific platform if auto-detection is wrong
agentpkg import ./some-dir --platform copilot
# Import a JSON export instead of a directory
agentpkg convert export.json --platform relevance-ai -o agent.agentpkg.zipUsing the OpenClaw adapter in code
import { convertOpenClaw } from "universal-agent/adapters/openclaw";
const pkg = convertOpenClaw("~/.config/openclaw", {
includeSecrets: true,
extractSqliteMemories: true,
});
await pkg.pack("my-agent.agentpkg.zip", "migration-passphrase");Security Auditing
Before installing an agent package you didn't write, scan it:
agentpkg audit agent.agentpkg.zipThe scanner checks for 26 threat patterns:
- Hidden unicode (12 patterns): zero width characters, RTL overrides, invisible tag characters
- Prompt injection (7 patterns): instruction overrides, jailbreak attempts, encoded payloads
- Suspicious tools (7 patterns): credential harvesting, data exfiltration, shell execution
CLI Commands
Create and Modify (interactive)
agentpkg create Build an agent step by step
agentpkg add memory <dir> Add memories interactively
agentpkg add skill <dir> Add skills with instructions
agentpkg add tool <dir> Add tool definitions
agentpkg add secret <dir> Add secrets (encrypted when packing)
agentpkg add cron <dir> Add scheduled tasks
agentpkg add rule <dir> Add guardrail rules
agentpkg set soul <dir> Rewrite the system prompt
agentpkg set model <dir> Change the model and temperature
agentpkg set description <dir> Update the agent descriptionImport
agentpkg import <dir> Import from any platform (auto-detects)
agentpkg convert <json> Convert a JSON export to agentpkg formatBuild and Deploy
agentpkg init <name> Scaffold an empty agent package
agentpkg pack <dir> Bundle into .agentpkg.zip
agentpkg compile <path> Compile to platform formatInspect and Verify
agentpkg validate <path> Check package structure is correct
agentpkg inspect <path> Show what's inside (including secret key names)
agentpkg unpack <zip> Extract a package
agentpkg audit <path> Run security scanOther
agentpkg update Update to latest version
agentpkg --version Show version (warns if outdated)Flags
--target <format> Which platform (claude-code|cursor|copilot|windsurf|crewai|openai|apm|all)
--passphrase <phrase> Encrypt or decrypt the secrets vault
--include-secrets Include actual credential values when importing
--no-zip Write unzipped directory instead of .zip (for import)
--platform <name> Source platform name for the import/convert command
-o <path> Where to write the outputSafety Features
agentpkg includes several protections:
Secrets are never written in plain text. They're encrypted with AES-256-GCM and scrypt key derivation before touching disk. The vault stores key names (not values) so you can inspect without decrypting.
Archives are validated before extraction. agentpkg reads file headers (magic bytes) to confirm a file is actually a zip or tar archive before extracting. Random or corrupted files are rejected with a clear error.
Shell commands use safe quoting. All paths passed to zip/tar/unzip are single-quoted to prevent injection from directory names with spaces or special characters.
Duplicates are caught early. You can't add two subagents with the same name (which would silently overwrite each other), and you can't add two memories with the same ID. Circular subagent references are also detected and rejected.
Format versions are checked on load. If you try to load a package created by a newer version of agentpkg, you'll get a clear error telling you to upgrade instead of silently loading corrupt data.
Generated code is properly escaped. Agent names and descriptions with quotes, newlines, colons, or special characters produce valid YAML, Python, and TOML. No more broken output from unusual names.
Project Structure
src/
├── types.ts 285 lines Type definitions
├── index.ts 976 lines AgentPackage class, validation, JSON adapter
├── compile.ts 698 lines 7 platform compilers
├── secrets.ts 365 lines Encrypted vault (AES-256-GCM + scrypt)
├── audit.ts 160 lines Security scanner
├── deps.ts 192 lines Dependency resolver
└── adapters/
└── openclaw.ts 669 lines OpenClaw filesystem adapter
bin/
└── cli.ts 1225 lines CLI (13 commands + interactive builders + platform importers)
test/
└── test.js 1246 lines 90 tests~5,800 lines of TypeScript. Zero runtime dependencies. 90 tests covering core operations, all compile targets, all platform importers, full round-trip flows, security validations, and CLI commands.
Contributing
git clone https://github.com/agrimshar/agentpkg.git
cd agentpkg
npm install
npm test # 90 tests
npm run build # TypeScript -> dist/License
MIT
