| name | hermes-paperclip-adapter |
| description | Integrate Hermes Agent as a managed AI employee in Paperclip companies with full tool access, persistent memory, and skill sync |
| triggers | ["set up hermes agent with paperclip","integrate hermes into my paperclip company","configure hermes paperclip adapter","run hermes as a paperclip employee","connect hermes agent to paperclip orchestration","deploy hermes with paperclip management","add hermes agent to my paperclip team","manage hermes sessions in paperclip"] |
Hermes Paperclip Adapter
Skill by ara.so — Hermes Skills collection.
The Hermes Paperclip Adapter runs Hermes Agent as a managed AI employee inside a Paperclip company. It provides full integration between Paperclip's orchestration/task system and Hermes's 30+ native tools, persistent memory, 80+ skills, and MCP support across 8 inference providers.
What It Does
- Runs Hermes as a Paperclip employee: Assign issues to Hermes agents, they wake up on heartbeats and comments, complete work, and report back
- Persistent session management: Sessions resume across heartbeats, maintaining conversation context and memory
- Structured transcript parsing: Converts raw Hermes stdout into typed
TranscriptEntry objects for proper UI rendering (tool cards, status icons)
- Skills sync: Merges Paperclip-managed skills with Hermes-native
~/.hermes/skills/ for unified skill management
- Multi-provider: Supports Anthropic, OpenRouter, OpenAI, Nous, OpenAI Codex, ZAI, Kimi Coding, MiniMax
- Comment-driven wakes: Agents respond to issue comments, not just task assignments
- Cost tracking: Captures token usage and costs from Hermes output
Installation
1. Install Prerequisites
pip install hermes-agent
hermes --version
2. Install the Adapter
npm install hermes-paperclip-adapter
3. Register in Paperclip Server
Edit your Paperclip server's adapter registry (server/src/adapters/registry.ts):
import * as hermesLocal from "hermes-paperclip-adapter";
import {
execute,
testEnvironment,
detectModel,
listSkills,
syncSkills,
sessionCodec,
} from "hermes-paperclip-adapter/server";
registry.set("hermes_local", {
...hermesLocal,
execute,
testEnvironment,
detectModel,
listSkills,
syncSkills,
sessionCodec,
});
Configuration
Basic Agent Config
Create a Hermes agent in Paperclip with adapterType: "hermes_local":
const agentConfig = {
name: "Hermes Engineer",
adapterType: "hermes_local",
adapterConfig: {
model: "anthropic/claude-sonnet-4",
maxIterations: 50,
timeoutSec: 300,
graceSec: 10,
persistSession: true,
enabledToolsets: ["terminal", "file", "web", "browser"],
worktreeMode: false,
checkpoints: false,
verbose: false,
quiet: true
}
};
Provider Configuration
The adapter auto-detects providers from model names:
{ model: "anthropic/claude-sonnet-4" }
{ model: "anthropic/claude-opus-4" }
{ model: "openrouter/anthropic/claude-3.5-sonnet" }
{ model: "openrouter/deepseek/deepseek-chat" }
{ model: "openai/gpt-4" }
{ model: "openai/o1" }
{ model: "nous/hermes-3" }
{
model: "claude-sonnet-4",
provider: "anthropic"
}
Set API keys via environment variables:
export ANTHROPIC_API_KEY=sk-ant-...
export OPENROUTER_API_KEY=sk-or-...
export OPENAI_API_KEY=sk-...
export NOUS_API_KEY=...
Toolset Control
Restrict available tools by specifying toolsets:
{
enabledToolsets: ["terminal", "file", "web"]
}
{
enabledToolsets: ["mcp", "vision"]
}
{
enabledToolsets: []
}
Available toolsets: terminal, file, web, browser, code_execution, vision, mcp, creative, productivity
Custom Prompts
Use template variables to customize agent instructions:
{
promptTemplate: `You are {{agentName}}, an AI engineer working for {{companyName}}.
{{#taskId}}
## Current Task
**{{taskTitle}}** (ID: {{taskId}})
{{taskBody}}
Complete this task using your available tools. When done, report results clearly.
{{/taskId}}
{{#commentId}}
## New Comment
You've been mentioned in a comment. Review the issue context and respond appropriately.
{{/commentId}}
Project: {{projectName}}
Company ID: {{companyId}}
Run ID: {{runId}}
API: {{paperclipApiUrl}}
`
}
Available variables:
{{agentId}}, {{agentName}}
{{companyId}}, {{companyName}}
{{runId}}, {{taskId}}, {{taskTitle}}, {{taskBody}}
{{projectName}}, {{commentId}}, {{wakeReason}}
{{paperclipApiUrl}}
Conditionals:
{{#taskId}}...{{/taskId}} — only when task assigned
{{#noTask}}...{{/noTask}} — only when no task
{{#commentId}}...{{/commentId}} — only when woken by comment
Usage Patterns
Creating a Hermes Employee
import { PaperclipClient } from "paperclip-client";
const client = new PaperclipClient({
apiUrl: process.env.PAPERCLIP_API_URL,
apiKey: process.env.PAPERCLIP_API_KEY
});
const agent = await client.agents.create({
name: "Hermes DevOps",
adapterType: "hermes_local",
adapterConfig: {
model: "anthropic/claude-sonnet-4",
maxIterations: 50,
timeoutSec: 600,
persistSession: true,
enabledToolsets: ["terminal", "file", "web"],
env: {
HERMES_LOG_LEVEL: "info"
}
},
schedule: {
cron: "*/15 * * * *"
}
});
console.log(`Created agent: ${agent.id}`);
Assigning Work
const issue = await client.issues.create({
title: "Optimize database queries",
body: `Review the API endpoint /api/users and optimize the database queries.
Current query time is ~500ms, target is <100ms.
Files:
- src/api/users.ts
- src/db/queries/users.ts
Run benchmarks before and after changes.`,
projectId: "proj_123"
});
await client.issues.assign({
issueId: issue.id,
agentId: agent.id
});
Monitoring Execution
const run = await client.runs.get(runId);
console.log(`Status: ${run.status}`);
console.log(`Model: ${run.modelUsed}`);
console.log(`Tokens: ${run.tokenUsage.total}`);
console.log(`Cost: $${run.cost}`);
console.log(`Session: ${run.sessionId}`);
for (const entry of run.transcript) {
console.log(`[${entry.type}] ${entry.content}`);
if (entry.type === "tool_use") {
console.log(` Tool: ${entry.toolName}`);
console.log(` Status: ${entry.status}`);
}
}
Skills Management
import { listSkills, syncSkills } from "hermes-paperclip-adapter/server";
const skills = await listSkills({
agentId: "agent_123",
companyId: "company_456"
});
console.log("Paperclip-managed skills:", skills.managed.length);
console.log("Hermes-native skills:", skills.native.length);
await syncSkills({
agentId: "agent_123",
companyId: "company_456",
enabledSkills: ["typescript-expert", "postgres-tuning", "docker-ops"]
});
Testing Environment
import { testEnvironment } from "hermes-paperclip-adapter/server";
const check = await testEnvironment({
hermesCommand: "hermes",
provider: "anthropic",
env: {
ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY
}
});
if (!check.success) {
console.error("Environment issues:", check.errors);
}
Auto Model Detection
import { detectModel } from "hermes-paperclip-adapter/server";
const detected = await detectModel({
hermesCommand: "hermes"
});
console.log(`Default model: ${detected.model}`);
console.log(`Provider: ${detected.provider}`);
Session State Management
import { sessionCodec } from "hermes-paperclip-adapter/server";
const validated = sessionCodec.decode(rawSessionState);
if (validated._tag === "Right") {
const session = validated.right;
console.log(`Session ID: ${session.sessionId}`);
console.log(`Messages: ${session.messageCount}`);
console.log(`Last activity: ${session.lastActivity}`);
} else {
console.error("Invalid session state:", validated.left);
}
Advanced Patterns
Git Worktree Isolation
Isolate agent work in separate git worktrees:
{
worktreeMode: true,
}
Filesystem Checkpoints
Enable rollback safety:
{
checkpoints: true,
}
Reasoning Effort Control
For o1/o3-style thinking models:
{
model: "openai/o1",
extraArgs: ["--reasoning-effort", "high"]
}
Custom Hermes CLI Path
{
hermesCommand: "/usr/local/bin/hermes-dev",
verbose: true
}
Extra Environment Variables
{
env: {
HERMES_LOG_LEVEL: "debug",
HERMES_CACHE_DIR: "/mnt/fast-storage/hermes-cache",
MCP_SERVER_URL: "http://localhost:8080"
}
}
Transcript Parsing
The adapter converts raw Hermes output into structured entries:
type TranscriptEntry =
| { type: "message"; role: "user" | "assistant"; content: string }
| { type: "tool_use"; toolName: string; status: "running" | "success" | "error"; input: any; output?: any }
| { type: "thinking"; content: string }
| { type: "memory_write"; key: string; value: any }
| { type: "error"; message: string; stderr?: string };
[
{ type: "message", role: "user", content: "Optimize the database queries" },
{ type: "tool_use", toolName: "read_file", status: "success", input: { path: "src/api/users.ts" } },
{ type: "thinking", : },
{ : , : , : , : { : } },
{ : , : , : , : },
{ : , : , : },
{ : , : , : }
]
Output Post-Processing
The adapter cleans Hermes ASCII formatting:
Before (raw Hermes output):
╔═══════════════════════════════════════╗
║ HERMES AGENT v2.1.0 ║
╚═══════════════════════════════════════╝
Results
=======
+---------------------------+----------+
| Metric | Value |
+---------------------------+----------+
| Query time (before) | 487ms |
| Query time (after) | 83ms |
+---------------------------+----------+
After (clean GFM markdown):
# Results
| Metric | Value |
|--------|-------|
| Query time (before) | 487ms |
| Query time (after) | 83ms |
Troubleshooting
Hermes CLI Not Found
which hermes
pip install hermes-agent
{
hermesCommand: "/path/to/hermes"
}
API Key Issues
echo $ANTHROPIC_API_KEY
echo $OPENROUTER_API_KEY
hermes chat -q "hello" --model anthropic/claude-sonnet-4
Session Resume Failures
{
persistSession: false
}
const run = await client.runs.get(runId);
console.log("Session state:", run.sessionState);
Timeout Issues
{
timeoutSec: 1800,
graceSec: 30,
maxIterations: 100
}
Tool Access Errors
{
enabledToolsets: ["terminal", "file"],
verbose: true
}
Stderr Noise
{
quiet: true
}
Skills Not Loading
ls ~/.hermes/skills/
ls node_modules/hermes-paperclip-adapter/skills/
chmod -R 755 ~/.hermes/skills/
hermes skills list
Memory/Context Issues
{
extraArgs: [
"--context-window", "200000",
"--compress-after", "150000"
]
}
Integration Examples
With GitHub Actions
name: Paperclip Hermes Agent
on:
schedule:
- cron: '*/30 * * * *'
jobs:
hermes:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install Hermes
run: pip install hermes-agent
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Trigger Paperclip Heartbeat
run: |
curl -X POST ${{ secrets.PAPERCLIP_API_URL }}/agents/${{ secrets.AGENT_ID }}/heartbeat \
-H "Authorization: Bearer ${{ secrets.PAPERCLIP_API_KEY }}"
env:
ANTHROPIC_API_KEY: ${{
With Docker
FROM node:20-slim
# Install Python and Hermes
RUN apt-get update && apt-get install -y python3 python3-pip
RUN pip3 install hermes-agent
# Install adapter
WORKDIR /app
COPY package*.json ./
RUN npm install hermes-paperclip-adapter
# Run Paperclip server with adapter
CMD ["npm", "start"]
With Kubernetes CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
name: hermes-agent
spec:
schedule: "*/15 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hermes
image: paperclip/hermes-agent:latest
env:
- name: ANTHROPIC_API_KEY
valueFrom:
secretKeyRef:
name: api-keys
key: anthropic
- name: PAPERCLIP_API_URL
value: "http://paperclip-server:3100/api"
restartPolicy: OnFailure
References