Files
DottaandPaperclip e38d6d16b6 feat(connections): add advanced provider setup and live browser qualification (#15341)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Users connect accounts and choose an agent harness and model.
> - The runtime change in #14970 supports custom providers on those
connections.
> - Normal setup must stay simple while advanced users can choose a
compatible gateway.
> - Shared connector rows and access controls keep these choices
consistent.
> - This pull request refines the agent setup UI and adds review stories
and repeatable browser qualification.
> - The qualification checks real tools and downloaded outputs, not only
a successful run status.

## Linked Issues or Issue Description

Refs #14970, #37, #13083, #14104, #14565, #12692.

The core implementation in #14970 is merged. This branch incorporates
its squash commit and targets `master`. Both PRs contain our
implementation. #14016 is a reference only and is not a dependency. This
PR has 96 changed files.

## What Changed

- Complete model-provider connector presentation beside other
connectors. Each row uses the existing Connect action and connection
list. Tags are stored without category UI. The base PR includes the
provider forms and routes.
- Show persistent Subscription, API Key, and Advanced choices. Label
Advanced as Custom Gateway. Reuse provider logos, connection lists, and
permissions controls. Default access to the organization and all agents
when permitted; keep narrowing controls under Advanced.
- Keep Configure reachable before subscription sign-in, so users can
select a supported environment when the default cannot sign in. Testing
and saving still require a connection. Show the execution environment in
Configure. Preserve the confirmed Connect choice. Editing a method,
credential, saved account, or advanced choice requires that current
choice to connect before testing or saving. Use matching model and
thinking-effort dropdowns and retain connection icons in selected
values.
- Preserve the new harness model default when switching an existing
OpenCode agent to Codex or Claude, and resolve user-selected model names
with the effective harness.
- Load popular OpenRouter models through the shared connection-model
discovery path. Keep explicit model lists and manual model entry
available.
- Group onboarding, connection setup, agent runtime, management,
recovery, and production-component stories under AI Connections /
Provider routing.
- Add an explicit-only provider-connections browser suite for managed
local or existing local/staging targets. Use private browser profiles
and credential handoffs. Support human-assisted subscription sign-in
without sharing passwords or tokens in reports.
- Verify persisted connection identity, runtime probes, tool execution,
exact artifact bytes, completion, and context-dependent follow-up.
Retain source/model provenance, cost bounds, closed error diagnostics,
original failures, and cleanup evidence.
- Add Gemini startup-model and skill-root fixes, Grok private-history
detection, ACP filesystem regression fixtures, selected-workspace
handling for local Hermes, and artifact-helper workspace fallback.
- Keep managed Grok runtime homes disposable. Remove host-side
transcript retention/restoration because private file modes do not
isolate same-user agent processes. Ignore earlier development archives
and use a fresh task handoff when history is unavailable. Verify the
absence of restored transcripts with a separate same-user process.
- Capture stopped-run diagnostics before deleting an attached-company
fixture agent. Track creation and owned sign-in receipts; revoke only
this attempt's accounts and never adopt a concurrent campaign's newly
created account. Preserve failure signals and final status through
cleanup.
- Require the requested environment in the saved agent and every run,
including follow-ups. Reject a forced incompatible target. Keep one
cancellation state through startup, every cell, reporting, and teardown
for SIGINT, SIGTERM, and SIGHUP. Stop further paid cells after
interruption. Document qualification limits.

## Verification

- Current head `b3bb3e94d577d43d9965a6b9daba039f599b2e49` includes
master `d9f600043`. The security fix in `a758fde31` passes full
workspace typecheck, production build, and 119 connection/Grok
regressions. The unchanged UI passes all 126
configuration/model-discovery tests and token gates. The final
published-guide correction passes Grok adapter typecheck. Earlier head
`eebd8225c` passed the complete deterministic runner suite (1,404 Vitest
tests and 128 Node tests) and all CI jobs. Current-head CI run
`37520147514` passed all 47 jobs, including the full sharded Vitest and
browser matrix, production build, and canary dry run. All 55 checks
completed: 53 successes and two expected skips. The current-head
security scan passed, Greptile is 5/5, and no review threads remain
open.
- A separate same-user process reproduced reading a restored Grok
transcript before the security fix. The regression now finds no
transcript. Existing fresh-session fallback and ordinary session
metadata behavior pass.
- The final account-choice and cleanup fixes pass 85 setup tests and 26
qualification-harness tests. Regressions verify that editing a
connection invalidates confirmation, Configure remains reachable before
sign-in, diagnostics are captured before fixture deletion, and
concurrent campaigns cannot adopt or revoke each other's accounts. UI
and E2E typechecks pass.
- The Storybook build and actual Chromium production-component stories
passed during this change. Review the neighboring AI Connections /
Provider routing stories, regular connector rows, three connection
modes, model discovery, and the single execution-environment control in
Configure.
- Cancellation smoke verified authenticated cleanup before browser close
for SIGINT, SIGTERM, and SIGHUP. Regressions cover interruption during
startup and reporting, missing-file ACP resource errors, and preserved
permission denials. Both ACP runtime versions and 54 ACPX/Grok
regressions passed. The deterministic connection-intent browser suite
passed two tests.
- Historical local qualification retained 43 passing API/gateway cells
out of 46, with downloaded outputs and follow-up receipts. These
attempts span earlier builds; they do not qualify this exact commit or
staging. Subscription combinations, Gemini overloads, and the unresolved
follow-up failure remain recorded rather than counted as passing.
- Use `pnpm test:e2e:runner -- --list --suite provider-connections` to
inspect the matrix. Follow `tests/runner-e2e/PROVIDER-CONNECTIONS.md`
for credentials, target URL, sign-in assistance, budget, evidence, and
cleanup. Paid live tests remain opt-in.

## Risks

- The core implementation in #14970 is merged. This PR adds no database
migration of its own.
- Subscription login needs an interactive provider session. Dedicated
accounts and staging qualification remain follow-up work; this PR does
not certify every login combination for production.
- Managed Grok transcript resume is deferred until provider history has
an OS isolation or authorized broker solution. Follow-ups start fresh
with Paperclip task context; earlier live Grok results do not qualify
this behavior.
- Gemini CLI 0.58.0 has an upstream ACP new-file error conversion
defect. Live overloads and one unresolved follow-up timeout remain
recorded. The stock CLI is unchanged, and those cases are not marked as
passing.
- Real-provider tests spend credits and use private credential/evidence
directories. The launcher requires explicit selection and checks target
ownership. It must not attach to a developer's database by accident.
- OpenClaw Gateway, Hermes Gateway, Claude Managed, AWS AgentCore,
Process, HTTP, and legacy ACPX local remain outside custom provider
setup.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository tools, code
execution, and browser testing. The exact deployment model ID and
context window size were not exposed in this session.

## Checklist


- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-06 15:21:22 -05:00
..
…

Paperclip Adapters for Hermes Agent

A Paperclip adapter package that lets you run Hermes Agent as a managed employee in a Paperclip company.

Hermes Agent is a full-featured AI agent by Nous Research with 30+ native tools, persistent memory, session persistence, 80+ skills, MCP support, and multi-provider model access.

This package owns both built-in Hermes adapter types:

  • hermes_local runs the local Hermes CLI as a child process. The package root exports remain compatible with the original local adapter.
  • hermes_gateway calls an already-running Hermes API server over HTTP/SSE. Gateway entrypoints live under the ./gateway export namespace.

Choose hermes_local when Paperclip and Hermes run on the same trusted host and Paperclip should start hermes chat for each heartbeat. Choose hermes_gateway when Hermes is already running as an API server, often on another host, in Docker, or behind a private-network/TLS endpoint. The adapter type keys did not change during package consolidation.

Key Features

This adapter provides:

  • 8 inference providers — Anthropic, OpenRouter, OpenAI, Nous, OpenAI Codex, ZAI, Kimi Coding, MiniMax
  • Skills integration — Scans both Paperclip-managed and Hermes-native skills (~/.hermes/skills/), with sync/list/resolve APIs
  • Structured transcript parsing — Raw Hermes stdout is parsed into typed TranscriptEntry objects so Paperclip renders proper tool cards with status icons and expand/collapse
  • Rich post-processing — Converts Hermes ASCII banners, setext headings, and +--+ table borders into clean GFM markdown
  • Comment-driven wakes — Agents wake to respond to issue comments, not just task assignments
  • Auto model detection — Reads ~/.hermes/config.yaml to pre-populate the UI with the user's configured model
  • Session codec — Structured validation and migration of session state across heartbeats
  • Benign stderr reclassification — MCP init messages and structured logs are reclassified so they don't appear as errors in the UI
  • Session source tagging — Sessions are tagged as tool source so they don't clutter the user's interactive history
  • Filesystem checkpoints — Optional --checkpoints for rollback safety
  • Thinking effort control — Passes --reasoning-effort for thinking/reasoning models

Hermes Agent Capabilities

Feature Claude Code Codex Hermes Agent
Persistent memory ❌ ❌ ✅ Remembers across sessions
Native tools ~5 ~5 30+ (terminal, file, web, browser, vision, git, etc.)
Skills system ❌ ❌ ✅ 80+ loadable skills
Session search ❌ ❌ ✅ FTS5 search over past conversations
Sub-agent delegation ❌ ❌ ✅ Parallel sub-tasks
Context compression ❌ ❌ ✅ Auto-compresses long conversations
MCP client ❌ ❌ ✅ Connect to any MCP server
Multi-provider Anthropic only OpenAI only ✅ 8 providers out of the box

Installation

This package ships with Paperclip core as the built-in hermes_local and hermes_gateway adapters. No Adapter manager installation is required for normal Paperclip use.

Prerequisites

  • Hermes Agent installed (pip install hermes-agent)
  • Python 3.10+
  • At least one LLM API key (Anthropic, OpenRouter, or OpenAI)

Quick Start

1. Optional: override the built-in for adapter development

For local adapter development, install the package from a local path in Adapter manager, or add an entry to ~/.paperclip/adapter-plugins.json and restart Paperclip. The external package can override either built-in Hermes adapter while it is enabled:

[
  {
    "packageName": "@paperclipai/hermes-paperclip-adapter",
    "localPath": "/absolute/path/to/paperclip/packages/adapters/hermes",
    "type": "hermes_local",
    "installedAt": "2026-06-23T00:00:00.000Z"
  }
]

Use "type": "hermes_gateway" with the same package when testing a gateway override.

The package root exports createServerAdapter() for the local server adapter, a declarative config schema for the generic agent form, and ./ui-parser for local run transcript parsing. Gateway entrypoints are exported from ./gateway, ./gateway/server, ./gateway/ui, ./gateway/cli, and ./gateway/ui-parser. Paperclip core imports these same package entrypoints for built-in adapter registration.

2. Create a local Hermes agent in Paperclip

In the Paperclip UI or via API, create an agent with adapter type hermes_local:

{
  "name": "Hermes Engineer",
  "adapterType": "hermes_local",
  "adapterConfig": {
    "model": "anthropic/claude-sonnet-4",
    "maxIterations": 50,
    "timeoutSec": 300,
    "persistSession": true,
    "enabledToolsets": ["terminal", "file", "web"]
  }
}

This mode shells out to the local hermes CLI. Paperclip injects runtime environment variables and captures stdout/stderr from the child process.

3. Create a Hermes gateway agent in Paperclip

Start Hermes with its API server enabled first:

API_SERVER_ENABLED=true \
API_SERVER_KEY=<generated-secret> \
hermes gateway run --replace --accept-hooks

Then create an agent with adapter type hermes_gateway:

{
  "name": "Hermes Gateway Engineer",
  "adapterType": "hermes_gateway",
  "adapterConfig": {
    "apiBaseUrl": "http://127.0.0.1:8642",
    "apiKey": "<same-value-as-API_SERVER_KEY>",
    "paperclipApiUrl": "http://127.0.0.1:3100",
    "sessionKeyStrategy": "issue",
    "timeoutSec": 600
  }
}

If the URL you have is the default Hermes dashboard at http://127.0.0.1:9119 or the default chat URL at http://127.0.0.1:9119/chat, Paperclip maps it to http://127.0.0.1:9119/api before calling Hermes API routes. /chat and the dashboard root are browser UI routes; Paperclip tests /api/health and starts runs with /api/v1/runs after mapping them to the API base.

This mode does not start Hermes. It creates runs with POST /v1/runs, streams Hermes events with SSE, polls run status as a fallback, and stops timed-out runs with POST /v1/runs/{run_id}/stop.

Compatibility with the old gateway package

@paperclipai/adapter-hermes-gateway remains as a deprecated compatibility shim for one release. It re-exports the gateway entrypoints from @paperclipai/hermes-paperclip-adapter/gateway and preserves the legacy exports for existing plugin installs. New installs and built-in Paperclip registrations should use @paperclipai/hermes-paperclip-adapter; the adapter type remains hermes_gateway.

Runtime API guidance

Hermes receives Paperclip runtime identity through environment variables:

  • PAPERCLIP_API_URL
  • PAPERCLIP_API_KEY
  • PAPERCLIP_RUN_ID

Prompts should reference those variables directly. Command output may redact secret values, so do not copy printed tokens into comments or config. Use Authorization: Bearer $PAPERCLIP_API_KEY on Paperclip API requests and X-Paperclip-Run-Id: $PAPERCLIP_RUN_ID on mutating issue requests. For multiline comments or status updates, preserve newlines with a heredoc plus jq --arg.

Hermes-originated Paperclip tasks

The package includes a Hermes skill/helper for the reverse direction: a user starts in Hermes and asks Hermes to create or update Paperclip work. This is not the same as Paperclip waking Hermes through hermes_local or hermes_gateway.

Configure Paperclip access in Hermes env/profile secrets, not prompt text:

PAPERCLIP_API_URL=http://127.0.0.1:3100/api
PAPERCLIP_BRIDGE_API_KEY=<task-bridge-scoped-agent-api-key>

Optional env values:

  • PAPERCLIP_COMPANY_ID
  • PAPERCLIP_AGENT_ID
  • PAPERCLIP_RUN_ID

The bundled paperclip-task-bridge skill provides deterministic helper commands:

node ./paperclip-task.mjs list-assigned
node ./paperclip-task.mjs create-task --parent-id "<approved-parent-issue-id>" --title "Investigate checkout failures" --description "Capture failing request and root cause."
node ./paperclip-task.mjs comment --issue PAP-123 --body "Found the failing request path."
node ./paperclip-task.mjs update-status --issue PAP-123 --status in_review --comment "Ready for review."

The helper reads credentials from environment variables and prints only JSON summaries. It supports create-task, comment, update-status, and list-assigned.

Create the bridge key with scope.kind = "task_bridge" plus a parentIssueId or projectId boundary. Do not use a normal claimed agent API key for internet-facing Hermes chat/webhook task-bridge operations.

4. Assign work

Create issues in Paperclip and assign them to your Hermes agent. On each heartbeat, Hermes will:

  1. Receive the task instructions
  2. Use its full tool suite to complete the work
  3. Report results back to Paperclip
  4. Persist session state for continuity

Configuration Reference

Core

Field Type Default Description
model string anthropic/claude-sonnet-4 Model in provider/model format
provider string (auto-detected) API provider: auto, openrouter, nous, openai-codex, zai, kimi-coding, minimax, minimax-cn
timeoutSec number 300 Execution timeout in seconds
graceSec number 10 Grace period before SIGKILL

Tools

Field Type Default Description
toolsets string (all) Comma-separated toolsets to enable (e.g. "terminal,file,web")

Available toolsets: terminal, file, web, browser, code_execution, vision, mcp, creative, productivity

Session & Workspace

Field Type Default Description
cwd string (assigned task workspace) Absolute working directory override. Without an override, use Paperclip's resolved task workspace.
persistSession boolean true Resume sessions across heartbeats
worktreeMode boolean false Git worktree isolation
checkpoints boolean false Enable filesystem checkpoints for rollback

Advanced

Field Type Default Description
hermesCommand string hermes Custom CLI binary path
verbose boolean false Enable verbose output
quiet boolean true Quiet mode (clean output, no banner/spinner)
extraArgs string[] [] Additional CLI arguments
env object {} Extra environment variables
promptTemplate string (built-in) Custom prompt template
paperclipApiUrl string http://127.0.0.1:3100/api Paperclip API base URL

Prompt Template Variables

Use {{variable}} syntax in promptTemplate:

Variable Description
{{agentId}} Paperclip agent ID
{{agentName}} Agent display name
{{companyId}} Company ID
{{companyName}} Company name
{{runId}} Current heartbeat run ID
{{taskId}} Assigned task/issue ID
{{taskTitle}} Task title
{{taskBody}} Task instructions
{{projectName}} Project name
{{paperclipApiUrl}} Paperclip API base URL
{{commentId}} Comment ID (when woken by a comment)
{{wakeReason}} Reason this run was triggered

Conditional sections:

  • {{#taskId}}...{{/taskId}} — included only when a task is assigned
  • {{#noTask}}...{{/noTask}} — included only when no task (heartbeat check)
  • {{#commentId}}...{{/commentId}} — included only when woken by a comment

Architecture

Paperclip                          Hermes Agent
┌──────────────────┐               ┌──────────────────┐
│  Heartbeat       │               │                  │
│  Scheduler       │───execute()──▶│  hermes chat -q  │
│                  │               │                  │
│  Issue System    │               │  30+ Tools       │
│  Comment Wakes   │◀──results─────│  Memory System   │
│                  │               │  Session DB      │
│  Cost Tracking   │               │  Skills          │
│                  │               │  MCP Client      │
│  Skill Sync      │◀──snapshot────│  ~/.hermes/skills│
│  Org Chart       │               │                  │
└──────────────────┘               └──────────────────┘

The adapter spawns Hermes Agent's CLI in single-query mode (-q). Hermes processes the task using its full tool suite, then exits. The adapter:

  1. Captures stdout/stderr and parses token usage, session IDs, and cost
  2. Parses raw output into structured TranscriptEntry objects (tool cards with status icons)
  3. Post-processes Hermes ASCII formatting (banners, setext headings, table borders) into clean GFM markdown
  4. Reclassifies benign stderr (MCP init, structured logs) so they don't show as errors
  5. Tags sessions as tool source to keep them separate from interactive usage
  6. Reports results back to Paperclip with cost, usage, and session state

Session persistence works via Hermes's --resume flag — each run picks up where the last one left off, maintaining conversation context, memories, and tool state across heartbeats. The sessionCodec validates and migrates session state between runs.

Skills Integration

The adapter scans two skill sources and merges them:

  • Paperclip-managed skills — bundled with the adapter, togglable from the UI
  • Hermes-native skills — from ~/.hermes/skills/, read-only, always loaded

The listSkills / syncSkills APIs expose a unified snapshot so the Paperclip UI can display both managed and native skills in one view.

Development

git clone https://github.com/paperclipai/paperclip
cd paperclip/packages/adapters/hermes
pnpm install
pnpm build

License

MIT — see LICENSE