Production-ready templates for packaging AI agents as installable software. Use when the user mentions: template, scaffold, boilerplate, starter, skeleton, package.json, pyproject.toml, Dockerfile, docker-compose, MCP server template, Claude Code plugin template, LangGraph deploy, install script, release action, GitHub Actions, agent packaging template, generate template, gen-template, cookiecutter, project structure
Production-ready templates for packaging AI agents and automations as installable software. Every template is complete, annotated, and ready to copy into a project.
{
"name": "@my-org/my-agent-mcp",
"version": "0.1.0",
"description": "MCP server that exposes my-agent capabilities as tools",
"license": "MIT",
"author": "my-org",
"type": "module",
"bin": {
"my-agent-mcp": "./dist/index.js"
},
"main": "./dist/index.js",
"files": [
"dist"
],
"scripts": {
"build": "tsc",
"dev": "tsc --watch",
"start": "node dist/index.js",
"lint": "eslint src/",
"prepublishOnly": "npm run build"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.12.0",
"zod": "^3.23.0"
},
"devDependencies": {
"@types/node": "^22.0.0",
"typescript": "^5.7.0",
"eslint": "^9.0.0"
},
"engines": {
"node": ">=18.0.0"
},
"keywords": [
"mcp",
"model-context-protocol",
"ai-agent"
]
}
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"declaration": true,
"sourceMap": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
#!/usr/bin/env node
// MCP Server skeleton — registers tools that an LLM client can invoke.
// The MCP SDK handles stdio transport, JSON-RPC framing, and capability negotiation.
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
// --- Server instance ---------------------------------------------------
const server = new McpServer({
name: "my-agent-mcp", // Appears in client UI (Claude Desktop, etc.)
version: "0.1.0", // Keep in sync with package.json
});
// --- Tool: greet -------------------------------------------------------
// Replace this with your agent's real capability.
// Each tool gets a name, description (shown to the LLM), input schema, and handler.
server.tool(
"greet", // Tool name (lowercase, hyphen-separated)
"Generate a greeting for the given name", // LLM-facing description
{
name: z.string().describe("Name to greet"), // Zod schema = JSON Schema for the LLM
},
async ({ name }) => {
// Your agent logic goes here.
// Return content as an array of text/image/resource blocks.
return {
content: [
{ type: "text", text: `Hello, ${name}! Welcome to my-agent.` },
],
};
}
);
// --- Tool: analyze (example with structured output) --------------------
server.tool(
"analyze",
"Analyze the provided text and return key insights",
{
text: z.string().describe("Text to analyze"),
depth: z.enum(["quick", "thorough"]).default("quick").describe("Analysis depth"),
},
async ({ text, depth }) => {
// Replace with your real analysis logic.
const wordCount = text.split(/\s+/).length;
const result = {
wordCount,
depth,
summary: `Analyzed ${wordCount} words at ${depth} depth.`,
};
return {
content: [
{ type: "text", text: JSON.stringify(result, null, 2) },
],
};
}
);
// --- Start server ------------------------------------------------------
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
// Server is now listening on stdin/stdout. The MCP client drives the conversation.
}
main().catch((error) => {
console.error("Fatal:", error);
process.exit(1);
});
# Publishes to npm on every GitHub Release (tag v*)
name: Publish to npm
on:
release:
types: [published]
permissions:
contents: read
id-token: write # Required for npm provenance
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "22"
registry-url: "https://registry.npmjs.org"
- run: npm ci
- run: npm run build
- run: npm run lint
# --provenance attaches a build attestation so users can verify origin
- run: npm publish --provenance --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
Customize: Change @my-org/my-agent-mcp to your package name. Replace the greet and analyze tools with your agent's real capabilities. Update version, description, author, and keywords.
[project]
name = "my-agent-mcp"
version = "0.1.0"
description = "MCP server exposing my-agent capabilities as tools"
readme = "README.md"
license = { text = "MIT" }
requires-python = ">=3.11"
authors = [{ name = "my-org" }]
keywords = ["mcp", "model-context-protocol", "ai-agent"]
dependencies = [
"mcp[cli]>=1.9.0",
"httpx>=0.27.0",
]
[project.scripts]
# Entry point for `uvx my-agent-mcp` or `pip install && my-agent-mcp`
my-agent-mcp = "my_agent_mcp.server:main"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["src/my_agent_mcp"]
"""
MCP Server for my-agent.
Run directly: python -m my_agent_mcp.server
Run via uvx: uvx my-agent-mcp
Run via mcp: mcp run my-agent-mcp
"""
from mcp.server.fastmcp import FastMCP
# --- Server instance ---------------------------------------------------
# The name appears in client UI (Claude Desktop, etc.)
server = FastMCP("my-agent-mcp")
# --- Tool: greet -------------------------------------------------------
# Replace with your agent's real capability.
# The docstring becomes the LLM-facing description.
# Type hints become the JSON Schema for the LLM.
@server.tool()
def greet(name: str) -> str:
"""Generate a greeting for the given name."""
return f"Hello, {name}! Welcome to my-agent."
# --- Tool: analyze -----------------------------------------------------
@server.tool()
def analyze(text: str, depth: str = "quick") -> str:
"""Analyze the provided text and return key insights.
Args:
text: Text to analyze.
depth: Analysis depth — "quick" or "thorough".
"""
word_count = len(text.split())
return f"Analyzed {word_count} words at {depth} depth."
# --- Entrypoint --------------------------------------------------------
def main():
server.run(transport="stdio")
if __name__ == "__main__":
main()
"""my-agent MCP server package."""
Customize: Change my-agent-mcp and my_agent_mcp to your package/module name. Replace greet and analyze with your tools. Add dependencies to pyproject.toml.
{
"name": "My Agent Plugin",
"version": "1.0.0",
"description": "One-sentence description of what this plugin does for the user",
"author": "my-org",
"skills": [
"skills/core-capability/SKILL.md"
],
"commands": [
"commands/run-agent/command.md"
]
}
{
"slug": "my-agent-plugin",
"display_name": "My Agent Plugin",
"tagline": "One-liner shown in marketplace search results",
"category": "ai-agents",
"tags": ["agent", "automation"],
"icon": "icon.png",
"repository": "https://github.com/my-org/my-agent-plugin",
"install_command": "git clone https://github.com/my-org/my-agent-plugin.git ~/.claude/plugins/my-agent-plugin"
}
---
name: core-capability
description: "Description of when this skill activates. Use when the user mentions: keyword1, keyword2, keyword3"
---
# Core Capability
## Context
Describe the domain knowledge this skill provides.
## Guidance
- Bullet point instructions for Claude when this skill is active.
- Reference specific frameworks, patterns, or rules.
- Keep guidance actionable — every line should change Claude's behavior.
## Reference
Key facts, tables, or data Claude needs to apply this skill.
---
name: run-agent
description: "Run the agent with the user's input"
---
# /run-agent
## Steps
1. Collect the user's input or goal.
2. Validate any required configuration (API keys, model selection).
3. Execute the agent's core capability.
4. Return structured results.
## Output Format
- Summary of what the agent did.
- Key results or artifacts produced.
- Suggested next steps.
# My Agent Plugin (v1.0.0)
Installed as a Claude Code plugin at `~/.claude/plugins/my-agent-plugin/`.
Skills are auto-invoked by the plugin system based on context.
Commands are user-invocable via `/command-name`.
## Available Skills
- **core-capability** — Description of what it does
## Available Commands
`/run-agent` — Description of what it does
Customize: Replace all instances of my-agent-plugin, my-org, core-capability, and run-agent. Add more skills and commands as needed. The CLAUDE.md is what appears in the host project's instructions.
# --- Stage 1: Build dependencies ---
FROM python:3.12-slim AS builder
WORKDIR /app
# Install build tools only in the builder stage
RUN pip install --no-cache-dir uv
COPY pyproject.toml uv.lock ./
RUN uv pip install --system --no-cache -r pyproject.toml
# --- Stage 2: Runtime ---
FROM python:3.12-slim AS runtime
WORKDIR /app
# Copy installed packages from builder
COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY --from=builder /usr/local/bin /usr/local/bin
# Copy application code last (cache-friendly layer ordering)
COPY src/ ./src/
# Non-root user for security
RUN useradd --create-home agent
USER agent
# Health check endpoint (see src/health.py)
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8080/health')"
EXPOSE 8080
CMD ["python", "-m", "src.main"]
services:
agent:
build: .
ports:
- "8080:8080"
env_file: .env # Load secrets from .env (never committed)
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
restart: unless-stopped
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: agent_db
POSTGRES_USER: agent
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-changeme} # Override in .env
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U agent"]
interval: 5s
timeout: 3s
retries: 5
redis:
image: redis:7-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
volumes:
pgdata:
# --- Required: AI Provider ---
ANTHROPIC_API_KEY=sk-ant-... # Get one at https://console.anthropic.com/
# OPENAI_API_KEY=sk-... # Optional fallback provider
# --- Required: Database ---
POSTGRES_PASSWORD=changeme # CHANGE THIS in production
DATABASE_URL=postgresql://agent:${POSTGRES_PASSWORD}@postgres:5432/agent_db
# --- Optional ---
REDIS_URL=redis://redis:6379/0
LOG_LEVEL=info # debug | info | warning | error
AGENT_MODEL=claude-sonnet-4-20250514 # Model to use for agent reasoning
Customize: Change the Python version if needed. Replace src.main with your actual module. Add agent-specific environment variables to .env.example. Adjust Postgres/Redis config for your data model.
# --- Stage 1: Install dependencies ---
FROM node:22-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
# --- Stage 2: Runtime ---
FROM node:22-alpine AS runtime
WORKDIR /app
# Copy node_modules from builder
COPY --from=builder /app/node_modules ./node_modules
# Copy application code
COPY src/ ./src/
COPY package.json ./
# Non-root user
RUN adduser -D agent
USER agent
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
CMD wget --quiet --tries=1 --spider http://localhost:8080/health || exit 1
EXPOSE 8080
CMD ["node", "src/index.js"]
services:
agent:
build: .
ports:
- "8080:8080"
env_file: .env
depends_on:
redis:
condition: service_healthy
restart: unless-stopped
redis:
image: redis:7-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
# --- Required: AI Provider ---
ANTHROPIC_API_KEY=sk-ant-... # Get one at https://console.anthropic.com/
# --- Optional ---
REDIS_URL=redis://redis:6379/0
LOG_LEVEL=info
PORT=8080
AGENT_MODEL=claude-sonnet-4-20250514
Customize: Change Node.js version if needed. Replace src/index.js with your entry point. Add a Postgres service if your agent needs persistent storage.
[project]
name = "my-agent-cli"
version = "0.1.0"
description = "CLI agent that does X"
readme = "README.md"
license = { text = "MIT" }
requires-python = ">=3.11"
authors = [{ name = "my-org" }]
dependencies = [
"click>=8.1.0",
"anthropic>=0.42.0",
"rich>=13.0.0", # Pretty terminal output
"python-dotenv>=1.0.0", # .env file support
]
[project.scripts]
# This creates the CLI command when installed via pip/pipx
my-agent = "my_agent_cli.cli:main"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["src/my_agent_cli"]
"""
CLI entry point for my-agent.
Install: pipx install my-agent-cli
Run: my-agent ask "What is the capital of France?"
"""
import os
import sys
import click
from dotenv import load_dotenv
load_dotenv() # Load .env file if present
@click.group()
@click.version_option()
def main():
"""My Agent CLI — one-line description of what it does."""
pass
@main.command()
@click.argument("prompt")
@click.option("--model", default="claude-sonnet-4-20250514", help="Model to use.")
def ask(prompt: str, model: str):
"""Send a prompt to the agent and print the response."""
api_key = os.environ.get("ANTHROPIC_API_KEY")
if not api_key:
click.echo(
"Error: ANTHROPIC_API_KEY not set.\n"
"Get one at: https://console.anthropic.com/\n"
"Then run: export ANTHROPIC_API_KEY=sk-ant-...",
err=True,
)
sys.exit(1)
# Lazy import: heavy deps load only when the command actually runs.
# This keeps `my-agent --help` and `my-agent --version` fast.
from anthropic import Anthropic
client = Anthropic(api_key=api_key)
response = client.messages.create(
model=model,
max_tokens=1024,
messages=[{"role": "user", "content": prompt}],
)
# Rich output for terminals, plain text for pipes
if sys.stdout.isatty():
from rich.console import Console
from rich.markdown import Markdown
console = Console()
console.print(Markdown(response.content[0].text))
else:
click.echo(response.content[0].text)
@main.command()
def config():
"""Show current configuration and check connectivity."""
api_key = os.environ.get("ANTHROPIC_API_KEY")
status = "set" if api_key else "MISSING"
click.echo(f"ANTHROPIC_API_KEY: {status}")
click.echo(f"Config file: ~/.my-agent/config.toml")
"""my-agent CLI package."""
Customize: Change my-agent-cli, my_agent_cli, and my-agent to your names. Replace the ask command with your agent's capabilities. Add more commands under @main.command().
{
"dependencies": ["."],
"graphs": {
"my_agent": "./src/my_agent/graph.py:graph"
},
"env": ".env"
}
[project]
name = "my-agent-langgraph"
version = "0.1.0"
description = "LangGraph agent that does X"
requires-python = ">=3.11"
dependencies = [
"langgraph>=0.3.0",
"langchain-anthropic>=0.3.0",
"langchain-core>=0.3.0",
]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["src/my_agent"]
"""
LangGraph agent graph definition.
This file defines the agent as a state machine. Each node is a function,
edges define transitions, and the state schema flows through the graph.
"""
from typing import Annotated, TypedDict
from langchain_anthropic import ChatAnthropic
from langchain_core.messages import BaseMessage
from langgraph.graph import StateGraph, END
from langgraph.graph.message import add_messages
# --- State schema -------------------------------------------------------
class AgentState(TypedDict):
"""State that flows through the graph. `messages` accumulates the conversation."""
messages: Annotated[list[BaseMessage], add_messages]
# --- Nodes --------------------------------------------------------------
model = ChatAnthropic(model="claude-sonnet-4-20250514")
def call_model(state: AgentState) -> dict:
"""Invoke the LLM with the current conversation history."""
response = model.invoke(state["messages"])
return {"messages": [response]}
def should_continue(state: AgentState) -> str:
"""Route to 'end' or back to the model based on the last message."""
last = state["messages"][-1]
# If the model made tool calls, continue the loop; otherwise finish.
if hasattr(last, "tool_calls") and last.tool_calls:
return "continue"
return "end"
# --- Graph assembly -----------------------------------------------------
workflow = StateGraph(AgentState)
workflow.add_node("agent", call_model)
workflow.set_entry_point("agent")
workflow.add_conditional_edges("agent", should_continue, {
"continue": "agent",
"end": END,
})
# Compile the graph — this is the object LangGraph Platform serves.
graph = workflow.compile()
FROM python:3.12-slim
WORKDIR /app
RUN pip install --no-cache-dir uv
COPY pyproject.toml ./
RUN uv pip install --system --no-cache -r pyproject.toml
COPY src/ ./src/
COPY langgraph.json ./
EXPOSE 8000
CMD ["langgraph", "up", "--host", "0.0.0.0", "--port", "8000"]
Customize: Rename my_agent and my-agent-langgraph. Add tool nodes between call_model and should_continue for agentic tool use. Extend AgentState with agent-specific fields.
# Multi-agent system: coordinator dispatches tasks to specialized workers.
# Shared state via Redis (ephemeral) and Postgres (persistent).
services:
# --- Coordinator: routes tasks to the right worker ---
coordinator:
build:
context: .
dockerfile: agents/coordinator/Dockerfile
ports:
- "8080:8080"
env_file: .env
depends_on:
redis:
condition: service_healthy
postgres:
condition: service_healthy
environment:
AGENT_ROLE: coordinator
WORKER_URLS: "http://researcher:8081,http://writer:8082"
restart: unless-stopped
# --- Worker: research agent ---
researcher:
build:
context: .
dockerfile: agents/researcher/Dockerfile
env_file: .env
environment:
AGENT_ROLE: researcher
PORT: 8081
depends_on:
redis:
condition: service_healthy
restart: unless-stopped
# --- Worker: writing agent ---
writer:
build:
context: .
dockerfile: agents/writer/Dockerfile
env_file: .env
environment:
AGENT_ROLE: writer
PORT: 8082
depends_on:
redis:
condition: service_healthy
restart: unless-stopped
# --- Shared state: Redis (task queue, ephemeral cache) ---
redis:
image: redis:7-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
volumes:
- redis_data:/data
# --- Shared state: Postgres (persistent results, audit log) ---
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: agents_db
POSTGRES_USER: agents
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-changeme}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U agents"]
interval: 5s
timeout: 3s
retries: 5
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
redis_data:
pgdata:
# --- Required: AI Provider (shared by all agents) ---
ANTHROPIC_API_KEY=sk-ant-...
# --- Required: Database ---
POSTGRES_PASSWORD=changeme
# --- Optional ---
LOG_LEVEL=info
COORDINATOR_MODEL=claude-sonnet-4-20250514
WORKER_MODEL=claude-haiku-4-20250514 # Cheaper model for workers
Customize: Add or remove worker services. Change WORKER_URLS in the coordinator to match. Each agent gets its own Dockerfile under agents/<name>/Dockerfile sharing the same base image pattern from Template 4.
# Build and publish agent binaries for macOS, Linux, and Windows.
# Triggered by pushing a tag like v1.0.0.
name: Release Agent Binaries
on:
push:
tags: ["v*"]
permissions:
contents: write # Required to create GitHub Releases
jobs:
build:
strategy:
matrix:
include:
- os: ubuntu-latest
target: x86_64-linux
artifact: my-agent-linux-amd64
- os: macos-latest
target: aarch64-darwin
artifact: my-agent-darwin-arm64
- os: windows-latest
target: x86_64-windows
artifact: my-agent-windows-amd64.exe
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
# Build a self-contained binary with PyInstaller
- run: pip install pyinstaller
- run: pip install -r requirements.txt
- run: pyinstaller --onefile --name ${{ matrix.artifact }} src/main.py
- uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact }}
path: dist/${{ matrix.artifact }}
release:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
with:
path: artifacts/
merge-multiple: true
# Generate checksums so users can verify integrity
- name: Generate SHA-256 checksums
run: |
cd artifacts
sha256sum * > SHA256SUMS.txt
- uses: softprops/action-gh-release@v2
with:
files: |
artifacts/*
generate_release_notes: true
Customize: Swap PyInstaller for your actual bui
<!-- Content truncated for initial SEO render. Open the source file tab for the full file. -->npx skills add phazurlabs/agent-install-templates下载完整 Skill 目录,包含 SKILL.md 及所有相关文件
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer