Skills Plugins MCP Prompt Model 博客 我的中心
開発 #api #agent

create-agent-adapter

Create or modify Paperclip agent adapters across server, UI, and CLI surfaces. Use when adding support for a new CLI agent, API agent, custom process, or adapter package.

DeepseekModel キュレーション済みスキル 品質 優秀 · 90 v1.0.0

取得

https://deepseekmodel.com/api/download.php?id=paperclipai-paperclip-agents-skills-create-agent-adapter-skill-md&format=skill
ダウンロード .skill 標準形式。system_prompt と model_config を収録し、任意の Agent で利用可能
.skill ファイルの system_prompt フィールドの実際の内容。
name create-agent-adapter description Create or modify Paperclip agent adapters across server, UI, and CLI surfaces. Use when adding support for a new CLI agent, API agent, custom process, or adapter package. Creating a Paperclip Agent Adapter An adapter bridges Paperclip's orchestration layer to a specific AI agent runtime (Claude Code, Codex CLI, a custom process, an HTTP endpoint, etc.). Each adapter is a self-contained package that provides implementations for three consumers : the server, the UI, and the CLI. 1. Architecture Overview packages/adapters/<name>/ src/ index.ts # Shared metadata (type, label, models, agentConfigurationDoc) server/ index.ts # Server exports: execute, sessionCodec, parse helpers execute.ts # Core execution logic (AdapterExecutionContext -> AdapterExecutionResult) parse.ts # Stdout/result parsing for the agent's output format ui/ index.ts # UI exports: parseStdoutLine, buildConfig parse-stdout.ts # Line-by-line stdout -> TranscriptEntry[] for the run viewer build-config.ts # CreateConfigValues -> adapterConfig JSON for agent creation form cli/ index.ts # CLI exports: formatStdoutEvent format-event.ts # Colored terminal output for `paperclipai run --watch` package.json tsconfig.json Three separate registries consume adapter modules: Registry Location Interface Server server/src/adapters/registry.ts ServerAdapterModule UI ui/src/adapters/registry.ts UIAdapterModule CLI cli/src/adapters/registry.ts CLIAdapterModule 2. Shared Types ( @paperclipai/adapter-utils ) All adapter interfaces live in packages/adapter-utils/src/types.ts . Import from @paperclipai/adapter-utils (types) or @paperclipai/adapter-utils/server-utils (runtime helpers). Core Interfaces // The execute function signature — every adapter must implement this interface AdapterExecutionContext { runId : string ; agent : AdapterAgent ; // { id, companyId, name, adapterType, adapterConfig } runtime : AdapterRuntime ; // { sessionId, sessionParams, sessionDisplayId, taskKey } config : Record < string , unknown >; // The agent's adapterConfig blob context : Record < string , unknown >; // Runtime context (taskId, wakeReason, approvalId, etc.) onLog : ( stream : "stdout" | "stderr" , chunk : string ) => Promise < void >; onMeta ?: ( meta : AdapterInvocationMeta ) => Promise < void >; authToken ?: string ; } interface AdapterExecutionResult { exitCode : number | null ; signal : string | null ; timedOut : boolean ; errorMessage ?: string | null ; usage ?: UsageSummary ; // { inputTokens, outputTokens, cachedInputTokens? } sessionId ?: string | null ; // Legacy — prefer sessionParams sessionParams ?: Record < string , unknown > | null ; // Opaque session state persisted between runs sessionDisplayId ?: string | null ; provider ?: string | null ; // "anthropic", "openai", etc. model ?: string | null ; costUsd ?: number | null ; resultJson ?: Record < string , unknown > | null ; summary ?: string | null ; // Human-readable summary of what the agent did clearSession ?: boolean ; // true = tell Paperclip to forget the stored session } interface AdapterSessionCodec { deserialize ( raw : unknown ): Record < string , unknown > | null ; serialize ( params : Record < string , unknown > | null ): Record < string , unknown > | null ; getDisplayId?( params : Record < string , unknown > | null ): string | null ; } Module Interfaces // Server — registered in server/src/adapters/registry.ts interface ServerAdapterModule { type : string ; execute ( ctx : AdapterExecutionContext ): Promise < AdapterExecutionResult >; testEnvironment ( ctx : AdapterEnvironmentTestContext ): Promise < AdapterEnvironmentTestResult >; sessionCodec ?: AdapterSessionCodec ; supportsLocalAgentJwt ?: boolean ; models ?: { id : string ; label : string }[]; agentConfigurationDoc ?: string ; } // UI — registered in ui/src/adapters/registry.ts interface UIAdapterModule { type : string ; label : string ; parseStdoutLine : ( line : string , ts : string ) => TranscriptEntry []; ConfigFields : ComponentType < AdapterConfigFieldsProps >; buildAdapterConfig : ( values : CreateConfigValues ) => Record < string , unknown >; } // CLI — registered in cli/src/adapters/registry.ts interface CLIAdapterModule { type : string ; formatStdoutEvent : ( line : string , debug : boolean ) => void ; } 2.1 Adapter Environment Test Contract Every server adapter must implement testEnvironment(...) . This powers the board UI "Test environment" button in agent configuration. type AdapterEnvironmentCheckLevel = "info" | "warn" | "error" ; type AdapterEnvironmentTestStatus = "pass" | "warn" | "fail" ; interface AdapterEnvironmentCheck { code : string ; level : AdapterEnvironmentCheckLevel ; message : string ; detail ?: string | null ; hint ?: string | null ; } interface AdapterEnvironmentTestResult { adapterType : string ; status : AdapterEnvironmentTestStatus ; checks : AdapterEnvironmentCheck []; testedAt : string ; // ISO timestamp } interface AdapterEnvironmentTestContext { companyId : string ; adapterType : string ; config : Record < string , unknown >; // runtime-resolved adapterConfig } Guidelines: Return structured diagnostics, never throw for expected findings. Use error for invalid/unusable runtime setup (bad cwd, missing command, invalid URL). Use warn for non-blocking but important situations. Use info for successful checks and context. Severity policy is product-critical: warnings are not save blockers. Example: for claude_local , detected ANTHROPIC_API_KEY must be a warn , not an error , because Claude can still run (it just uses API-key auth instead of subscription auth). 3. Step-by-Step: Creating a New Adapter 3.1 Create the Package packages/adapters/<name>/ package.json tsconfig.json src/ index.ts server/index.ts server/execute.ts server/parse.ts ui/index.ts ui/parse-stdout.ts ui/build-config.ts cli/index.ts cli/format-event.ts package.json — must use the four-export convention: { "name" : "@paperclipai/adapter-<name>" , "version" : "0.0.1" , "private" : true , "type" : "module" , "exports" : { "." : "./src/index.ts" , "./server" : "./src/server/index.ts" , "./ui" : "./src/ui/index.ts" , "./cli" : "./src/cli/index.ts" } , "dependencies" : { "@paperclipai/adapter-utils" : "workspace:*" , "picocolors" : "^1.1.1" } , "devDependencies" : { "typescript" : "^5.7.3" } } 3.2 Root index.ts — Adapter Metadata This file is imported by all three consumers (server, UI, CLI). Keep it dependency-free (no Node APIs, no React). export const type = "my_agent" ; // snake_case, globally unique export const label = "My Agent (local)" ; export const models = [ { id : "model-a" , label : "Model A" }, { id : "model-b" , label : "Model B" }, ]; export const agentConfigurationDoc = `# my_agent agent configuration ...document all config fields here... ` ; Required exports: type — the adapter type key, stored in agents.adapter_type label — human-readable name for the UI models — available model options for the agent creation form agentConfigurationDoc — markdown describing all adapterConfig fields (used by LLM agents configuring other agents) Writing agentConfigurationDoc as routing logic: The agentConfigurationDoc is read by LLM agents (including Paperclip agents that create other agents). Write it as routing logic , not marketing copy. Include concrete "use when" and "don't use when" guidance so an LLM can decide whether this adapter is appropriate for a given task. export const agentConfigurationDoc = `# my_agent agent configuration Adapter: my_agent Use when: - The agent needs to run MyAgent CLI locally on the host machine - You need session persistence across runs (MyAgent supports thread resumption) - The task requires MyAgent-specific tools (e.g. web search, code execution) Don't use when: - You need a simple one-shot script execution (use the "process" adapter instead) - The agent doesn't need conversational context between runs (process adapter is simpler) - MyAgent CLI is not installed on the host Core fields: - cwd (string, required): absolute working directory for the agent process ... ` ; Adding explicit negative cases improves adapter selection accuracy. One concrete anti-pattern is worth more than three paragraphs of description. 3.3 Server Module server/execute.ts — The Core This is the most important file. It receives an AdapterExecutionContext and must return an AdapterExecutionResult . Required behavior: Read config — extract typed values from ctx.config using helpers ( asString , asNumber , asBoolean , asStringArray , parseObject from @paperclipai/adapter-utils/server-utils ) Build environment — call buildPaperclipEnv(agent) then layer in PAPERCLIP_RUN_ID , context vars ( PAPERCLIP_TASK_ID , PAPERCLIP_WAKE_REASON , PAPERCLIP_WAKE_COMMENT_ID , PAPERCLIP_APPROVAL_ID , PAPERCLIP_APPROVAL_STATUS , PAPERCLIP_LINKED_ISSUE_IDS ), user env overrides, and auth token Resolve session — check runtime.sessionParams / runtime.sessionId for an existing session; validate it's compatible (e.g. same cwd); decide whether to resume or start fresh Render prompt — use renderTemplate(template, data) with the template variables: agentId , companyId , runId , company , agent , run , context Call onMeta — emit adapter invocation metadata before spawning the process Spawn the process — use runChildProcess() for CLI-based agents or fetch() for HTTP-based agents Parse output — convert the agent's stdout into structured data (session id, usage, summary, errors) Handle session errors — if resume fails with "unknown session", retry with a fresh session and set clearSession: true Return AdapterExecutionResult — populate all fields the agent runtime supports Environment variables the server always injects: Variable Source PAPERCLIP_AGENT_ID agent.id PAPERCLIP_COMPANY_ID agent.companyId PAPERCLIP_API_URL Server's own URL PAPERCLIP_RUN_ID Current run id PAPERCLIP_TASK_ID context.taskId or context.issueId PAPERCLIP_WAKE_REASON context.wakeReason PAPERCLIP_WAKE_COMMENT_ID context.wakeCommentId or context.commentId PAPERCLIP_APPROVAL_ID context.approvalId PAPERCLIP_APPROVAL_STATUS context.approvalStatus PAPERCLIP_LINKED_ISSUE_IDS context.issueIds (comma-separated) PAPERCLIP_API_KEY authToken (if no explicit key in config) server/parse.ts — Output Parser Parse the agent's stdout format into structured data. Must handle: Session identification — extract session/thread ID from init events Usage tracking — extract token counts (input, output, cached) Cost tracking — extract cost if available Summary extraction — pull the agent's final text response Error detection — identify error states, extract error messages Unknown session detection — export an is<Agent>UnknownSessionError() function for retry logic Treat agent output as untrusted. The stdout you're parsing comes from an LLM-driven process that may have executed arbitrary tool calls, fetched external content, or been influenced by prompt injection in the files it read. Parse defensively: Never eval() or dynamically execute anything from output Use safe extraction helpers ( asString , asNumber , parseJson ) — they return fallbacks on unexpected types Validate session IDs and other structured data before passing them through If output contains URLs, file paths, or commands, do not act on them in the adapter — just record them server/index.ts — Server Exports export { execute } from "./execute.js" ; export { testEnvironment } from "./test.js" ; export { parseMyAgentOutput, isMyAgentUnknownSessionError } from "./parse.js" ; // Session codec — required for session persistence export const sessionCodec : AdapterSessionCodec = { deserialize ( raw ) { /* raw DB JSON -> typed params or null */ }, serialize ( params ) { /* typed params -> JSON for DB storage */ }, getDisplayId ( params ) { /* -> human-readable session id string */ }, }; server/test.ts — Environment Diagnostics Implement adapter-specific preflight checks used by the UI test button. Minimum expectations: Validate required config primitives (paths, commands, URLs, auth assumptions) Return check objects with deterministic code values Map severity consistently ( info / warn / error ) Compute final status: fail if any error warn if no errors and at least one warning pass otherwise This operation should be lightweight and side-effect free. 3.4 UI Module ui/parse-stdout.ts — Transcript Parser Converts individual stdout lines into TranscriptEntry[] for the run detail viewer. Must handle the agent's streaming output format and produce entries of these kinds: init — model/session initialization assistant — agent text responses thinking — agent thinking/reasoning (if supported) tool_call — tool invocations with name and input tool_result — tool results with content and error flag user — user messages in the conversation result — final result with usage stats stdout — fallback for unparseable lines export function parseMyAgentStdoutLine ( line : string , ts : string ): TranscriptEntry [] { // Parse JSON line, map to appropriate TranscriptEntry kind(s)
このスキルを起動するキーワード。クリックでコピーできます。

このスキルにはトリガーワードがありません。

ダウンロードした .skill に含まれるフィールド。
フィールド 説明
formatフォーマット識別子(skill/v1)
skill_idスキル固有 ID
nameスキル名
versionバージョン
description説明
categoryカテゴリ(配列)
trigger_wordsトリガーワード
tagsタグ
sourceソース
source_urlソース URL(本ページ)
exported_atエクスポート日時(ダウンロード毎)
system_promptシステムプロンプト本文
model_configモデル設定:provider / model / temperature / max_tokens / top_p
examplesサンプル
install_guide各プラットフォームの導入説明(Coze / Dify / Claude / カスタム)
同じスキルを各プラットフォーム形式で出力できます。
.skill 標準形式。system_prompt と model_config を収録し、任意の Agent で利用可能 ダウンロード
.skillpro 拡張形式。scripts / tools / dependencies / hooks を含む ダウンロード
.json 純粋な JSON 出力。system_prompt とモデル設定のみ ダウンロード
Coze frontmatter 付き Markdown。Coze へのインポート用 ダウンロード
Dify Dify DSL。アプリ作成後にそのままインポート ダウンロード

每日精选 Skill 推荐,免费送到你邮箱

输入邮箱,每天接收一个精选 AI Agent 技能推荐。完全免费,持续更新。

提交后我们会发送一封确认邮件,点击邮件里的链接才会开始收信。

完全免费,取消任意时间。我们不会发送垃圾邮件。