DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

A2a — DeepSeek Harness 插件(DSH Plugin)
← Plugins

dsh-a2a

A2a

dsh-a2a:DeepSeek Harness 的 A2A v1.0——将该 harness 暴露为 A2A agent,并从 agent 工具调用远程 A2A agents。

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add dsh-a2a@0.7.1
README兼容性版本

兼容性与来源证明

A2a 以 dsh-a2a 发布,当前版本为 0.7.1。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
web
发布来源
npm
Registry 更新时间
2026/9/20

版本

0.7.1stable
2026/8/31
0.7.0stable
2026/8/31
0.5.0stable
2026/8/24
查看其余 7 个版本收起版本
0.4.2stable
2026/8/21
0.4.1stable
2026/8/19
0.4.0stable
2026/8/19
0.3.0stable
2026/8/19
0.2.1stable
2026/8/18
0.2.0stable
2026/8/18
0.1.0stable
2026/8/15

相关插件

正在加载相关插件…

最新版
0.7.1
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
430.1 kB
文件数
9
Surface
web
许可证
MIT
发布源
npm
GitHub
★ 1
周下载
75
最近提交
2026/8/31
查看源码 ↗项目主页 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题
DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录

相关插件

继续浏览 agents-orchestration 分类下经过校验的插件。

Headless@deepseek-ai/dsh-headlessdsh one-shot bundle:基于 dsh-base 的直接核心 Agent/Session 运行器,不包含 Host、HTTP 或浏览器层Experimental Agent Team Web Profile@deepseek-ai/dsh-experimental-agent-team-web-profile用于 Agent Teams Remote 和 UI 插件的实验性 Web 配置层Subagent Codex@deepseek-ai/dsh-subagent-codex基于官方 app-server 协议的一次性 Codex 子代理提供程序Subagent Claude Code@deepseek-ai/dsh-subagent-claude-code基于官方 Agent SDK 的一次性 Claude Code 子代理提供方

README

dsh-a2a

A2A v1.0 for DeepSeek Harness — expose the harness as an A2A agent, and let harness agents delegate to remote A2A agents.

One plugin, two halves, built on the official @a2a-js/sdk (A2A Protocol v1.0):

  • Server — a self-contained HTTP endpoint exposing the harness as an A2A agent: Agent Card discovery, JSON-RPC (the mandatory transport, SSE streaming included), and the HTTP+JSON REST surface. Every A2A contextId maps to a persistent harness session, so follow-up messages continue the same conversation.
  • Client — the a2a_call / a2a_list model tools, so harness agents can delegate work to remote A2A agents from a config-driven registry with header auth.

✨ Features

  • 🤖 Multi-agent server — one endpoint serves several agents, each at its own /agents/<id> with its own preset, model route, workspace group, Agent Card identity, and skills; one contextId maps to one persistent harness session per agent (deterministic sha256(contextId) ids), preset-mounted, persistent across turns.
  • 📇 Per-agent Agent Card skills — each agent advertises its abilities as A2A AgentSkill[] (id / name / description) on its own card, so an A2A client can route by what an agent is for.
  • 🎛️ Live served-agent management — the settings tab's inbound editor adds / removes / re-identifies a served agent; a save reconciles the running server without a restart.
  • 🔑 Token view + rotation — the settings tab shows the Bearer key (masked by default, reveal + copy) and rotates it live, persisting the new key to the settings document.
  • 🔌 Full A2A v1.0 wire — /.well-known/agent-card.json, JSON-RPC SendMessage / SendStreamingMessage / GetTask / CancelTask / ListTasks (SSE for streaming), REST message:send / tasks/* — all through the official SDK's request handler.
  • 🔒 Header auth on the client side — per-agent headers with ${ENV_VAR} placeholders resolved at call time; credentials never sit in the config.
  • 🔑 Bearer auth on the server side — with server.apiKey set, every request except the Agent Card must present Authorization: Bearer <key>; the card can also advertise a publicUrl behind a reverse proxy.
  • 🎛️ Per-request preset and model — a caller can name the preset and the model route on the A2A metadata map instead of using the deployment's route (see Per-request overrides).
  • 🧭 Model route and workspace — A2A conversations can pin a provider/model pair and live in their own workspace group (A2A, ~/.a2a-sessions by default).
  • ⏱️ Turn deadlines — a slow turn is cancelled (turnTimeoutMs, default 5 min) so the next message is never stuck.
  • 🛡️ Fail-loud config — bad URLs, empty names, or out-of-range ports throw at plugin load.
  • 🧪 Real-wire tests — the server half is exercised end to end with the official A2A client over a live HTTP port.

🚀 Quick Start

dsh plugin --profile web add dsh-a2a

export A2A_HOST=127.0.0.1
export A2A_PORT=8899

dsh web   # restart, then GET http://127.0.0.1:8899/.well-known/agent-card.json

Call the agent (JSON-RPC, blocking):

curl -s http://127.0.0.1:8899/ -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"SendMessage","params":{"message":{"role":"user","messageId":"m1","parts":[{"kind":"text","text":"hi"}],"contextId":"demo"}}}'

A2A_ENABLED=0 runs the client tools only (no listener).

⚙️ Configuration

The mounted row lives in ~/.dsh/profiles/web/cordis.patch.yml:

- id: a2a
  name: dsh-a2a
  config:
    server:
      enabled: true            # serve the A2A endpoint at all
      host: 127.0.0.1          # A2A_HOST
      port: 8899               # A2A_PORT
      turnTimeoutMs: 300000    # per-turn deadline
      allowOverrides: true     # let callers pick preset/model per request
      agents:                  # LOCAL agents served at /agents/<id>
        - id: support
          name: Support Agent
          description: Answers internal support questions.
          version: '0.1.0'
          preset: standard
          workspaceTitle: A2A
          skills:
            - id: query-orders
              name: Query orders
              description: Look up an order's status and timeline.
    agents: []                 # remote agents reachable from a2a_call

Each local agent lives at /agents/<id>/.well-known/agent-card.json and gets a session namespace (a2a-<id>-<hash>), its own workspace group, and its own Agent Card. The legacy single-agent form (server.preset / server.agentCard) still works: when server.agents is empty, one agent is derived from it.

FieldDefaultMeaning
server.enabledtrueServe the A2A endpoint; client tools work regardless
server.host / server.port127.0.0.1 / 8899Listen address (env A2A_HOST / A2A_PORT)
server.presetstandardPreset mounted into each A2A conversation agent
server.turnTimeoutMs300000Per-turn deadline; a slow turn is cancelled
server.allowOverridestrueWhether callers may pick preset/model per request via metadata; when false their overrides are dropped (and logged)
server.publicUrl—Public URL advertised on the Agent Card (required behind a reverse proxy); env A2A_PUBLIC_URL
server.apiKey—When set, every request except the Agent Card must present Authorization: Bearer <key>; env A2A_API_KEY
server.provider / server.model—Model route for A2A conversations, must be set as a pair; falls back to the harness default model; env A2A_PROVIDER / A2A_MODEL
server.cwd~/.a2a-sessionsWorking directory for A2A conversations (doubles as the sidebar workspace path); env DSH_A2A_CWD
server.workspaceTitleA2ASidebar group title for A2A conversations
server.agents[].id—URL slug under /agents/ (must be URL-safe), e.g. support
server.agents[].name / description / version—This agent's Agent Card identity
server.agents[].preset—Preset mounted into this agent's conversations

🎛️ Per-request overrides

By default every conversation uses the deployment's route: the configured server.preset and provider/model pair. A caller can pick its own instead by naming them on the A2A metadata map:

curl -s http://127.0.0.1:8899/ -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"SendMessage","params":{
        "message":{"role":"user","messageId":"m1","parts":[{"kind":"text","text":"hi"}],"contextId":"demo"},
        "metadata":{"agentPreset":"general","model":"model-a"}
      }}'
KeyAliasesMeaningApplies
agentPresetpresetPreset id to compose the agent from, overriding server.preseton the request that creates the session
model—Model id, overriding server.modelon every request, and it sticks for the rest of the session
provider—Provider route, paired with the configured (or default) modelon every request

The two ride different lifetimes because the harness gives them different ones:

  • A preset composes an agent — it mounts tools and skills at session creation. Once a session exists its composition is fixed, so a preset on a later turn is ignored and logged: swapping tools mid-conversation would leave tool calls the new composition cannot make. Send the preset on the first message (or use a fresh contextId).
  • The model is a per-step route, so a live session is switched onto the requested model without losing the conversation — or the KV-cache prefix its history already earned.

Precedence and edge cases:

  • params.message.metadata wins over params.metadata; writing the same value to both — as the REST message:send shape invites — is unambiguous, and callers that only know one of them still work.
  • A bare model is paired with server.provider, falling back to the harness default model's provider: callers know the model they want, not the route serving it. Without any provider to pair with, the task fails rather than answering on a model the caller did not ask for.
  • A malformed value (a non-string, or one that could escape the preset root) fails the task with a message naming the key.
  • An unknown preset fails the task and lists the ids this deployment does supply.
  • Set server.allowOverrides: false to lock the deployment's route: overrides are then dropped and logged, and the request is still answered.

🏷️ Deployment customization (recommended)

dsh assemblies are layered: the bundle's own patch (npm-distributed) → the profile's cordis.patch.yml → environment variables. When giving a deployment its own identity, put each piece on the right layer:

  • Keep the shipped cordis.patch.yml generic — it reaches every npm consumer, so never bake deployment-specific identity (a bespoke preset, a dedicated Agent Card name/description) into it.
  • Deployment identity goes in the profile override layer — override the a2a row by id in ~/.dsh/profiles/web/cordis.patch.yml (no - insert: prefix, and spell out the full server block):
# ~/.dsh/profiles/web/cordis.patch.yml
- id: a2a
  name: dsh-a2a
  config:
    server:
      enabled: true
      host: 127.0.0.1
      port: 8899
      preset: my-support-preset      # deployment-specific preset
      turnTimeoutMs: 300000
      agentCard:
        name: My Support Agent       # deployment-specific identity
        description: Answers internal support questions.
        version: '0.1.0'
    agents: []
  • Secrets go in environment variables — the real values of publicUrl / apiKey / provider / model never sit in any YAML; keep the !!js process.env.XXX expressions and inject the values at launch (systemd users can use EnvironmentFile):
# /etc/dsh-web.env (systemd EnvironmentFile example)
A2A_PUBLIC_URL=https://gateway.example.com/
A2A_API_KEY=<secret>
A2A_PROVIDER=venus
A2A_MODEL=model-b

Patch-layer changes are read at assembly time — restart dsh web to apply them. The GUI registry (agents) is the exception: saves hot-reload.

💬 Model tools

ToolWhat it does
a2a_listLists the registered remote A2A agents (name + description).
a2a_callSends a prompt to one registered agent and returns its completed text reply.

🏗️ How it works

  • The server is a standalone Node HTTP listener (not a route on the web GUI): it serves several local agents, each at /agents/<id>/... with its own Agent Card, JSON-RPC + REST surface, preset-mounted executor, and session namespace. The root /.well-known/agent-card.json returns the first agent (there is no default agent at /); server.agents[] is the multi-agent form, and the legacy single-agent config derives one agent. Lifecycle is tied to the Cordis fiber — the listener starts on plugin load and closes (sockets included) on plugin disposal.
  • Each agent's executor implements the SDK's AgentExecutor contract: publish a task event, run one harness turn (followup → whenIdle with deadline → cancel on timeout), publish the reply as a message event, then a terminal statusUpdate. CancelTask reaches the right agent through the running-task table. The executor per agent is keyed by contextId (session namespace a2a-<agentId>-<hash>), so follow-up turns continue the same conversation.
  • The client resolves the registry through the SDK's ClientFactory (JSON-RPC + REST transports) with an authenticating fetch that injects the per-agent headers.

⚠️ Limitations

  • Inbound authentication: since 0.3.0 server.apiKey enforces a Bearer token on every request except the Agent Card (which must stay publicly readable); for larger deployments, still put the port behind an authenticating gateway or a reverse proxy. The Agent Card advertises no security schemes.
  • One executor instance serves every context of one agent (each /agents/<id> gets its own); sessions resume across turns but a dsh restart creates fresh in-memory state. The root /.well-known/agent-card.json returns the first agent only — address a specific agent at /agents/<id>/....
  • A model override switches sessions this executor instance created. One adopted from outside it — opened in the web UI, or resumed from disk — has no route handle to switch, so the override is logged and ignored; the reply keeps the model it was created with. Sending the model again after the executor creates the session works as expected.
  • Outbound registry edits require a profile patch + restart 0.2.0: GUI-configurable. The Plugins → Plugin configuration section ships an "A2A remote agents" card over the a2a settings namespace (schema defaults → row-config base → user overrides); a save hot-reloads the running tools, and a reset re-inherits the deployment registry.

🧪 Development

npm run check   # biome + typecheck + vitest (59 tests) + build

The suite covers config validation, the Agent Card + JSON-RPC round trip through the official A2A client against a real HTTP listener, per-context session continuity, task cancellation, header auth, per-request overrides, and the model-facing tools.

📄 License

MIT

server.agents[].provider / model—This agent's model route (must be a pair); falls back to the harness default
server.agents[].cwd / workspaceTitleserver.cwd / A2AThis agent's workspace directory / group title
server.agents[].skills[]A2A AgentSkill[] (id / name / description) advertised on this agent's card
server.agentCard.*—Legacy single-agent identity (used when server.agents is empty)
agents[].name / url—Remote registry name for a2a_call + Agent Card URL
agents[].headers{}Request headers; ${ENV_VAR} placeholders resolved at call time
agents[].description''Shown by a2a_list