跳到正文
cccskills
免费在 GitHub 公开

agent-capabilities

Give a Boring UI in-app agent capabilities and gate them safely - custom tools, workspace file access (file guard, present), Approve/Deny approvals, ask_user questions, sub-agents (delegate), schedules, sandboxes and self-evolving tools. Use when asked to "add a tool to the agent", "let the agent edit files", "require approval before X", "ask the user a question", "add a sub-agent/delegate", "schedule a follow-up/reminder", "dry-run/sandbox the agent", "let the agent write its own tools", or when choosing which tools to gate with requireApproval or createApprovalExtension.

中文简介正在准备中。当前显示原文说明。

实测评分 未实测

查看安装方法

包含的文件(1)

  • SKILL.md8.9 KB

SKILL.md(原文)

安装前可以查看交给 AI 代理的指令内容。

Agent capabilities

Every capability is a native Pi tool or extension that you hand to defineAgent (from @hachej/boring-agent/agents). The host decides what the agent may do. Start from the server in the build-agent-app skill.

const agent = defineAgent({
  id: 'writer', model: { provider: 'openai', modelId: 'gpt-5-mini' }, instructions: '...',
  tools: [/* tool registrations */],
  extensions: [/* native extensions, in order */],
  delegates: [/* sub-agents */],
});
agent.install(registry);   // before Harness.open

Custom tools

Use Pi's defineTool and Type. Return text in output.

import { defineTool } from '@earendil-works/pi-durable';
import { Type } from '@earendil-works/pi-ai';

const lookupOrder = defineTool({
  name: 'lookup_order', description: 'Look up a fictional order by its number.',
  parameters: Type.Object({ number: Type.String() }, { additionalProperties: false }),
  execute: async ({ number }) => ({ output: [{ type: 'text', text: JSON.stringify(await orders.get(number)) }] }),
});

The host's execute owns the data access, credentials and limits. For a tool described by a raw JSON Schema (an MCP inputSchema), use jsonSchemaTool({ name, description, parameters, execute }) from /agents.

Files

  • Give the agent Pi's own createReadTool(), createWriteTool(), createEditTool() (and createBashTool() with a shell) from @earendil-works/pi-durable/tools, in one defineExtension.
  • Add createFileGuard({ workspace: { files, root, access } }) from /file-guard after that extension. It routes read/write/edit through the workspace provider, refuses writes to files the conversation has not read at their current revision, and records agent edits in file history.
  • Add createPresentTool({ workspace }) from /artifacts so the agent can open a file in the page.
  • Use the same files provider everywhere (guard, present, revision route). Never a second copy.
  • Several people, one agent: resolve the workspace per call with @hachej/boring-agent/workspaces (Workspace per call).

Approvals

Gate a tool so each call waits for the person's Approve or Deny. Deny returns an error starting with DENIED_PREFIX, and the tool never runs. Pending approvals survive a restart.

Gate stock or third-party tools by name with an extension:

import { createApprovalExtension } from '@hachej/boring-agent/approval';

const approvals = createApprovalExtension({ tools: {
  write: true, edit: true,
  bash: { summarize: args => `Run: ${args.command}` },
  http_request: { when: args => args.method !== 'GET', summarize: args => `${args.method} ${args.url}` },
} });
defineAgent({ ..., extensions: [fileTools, createFileGuard({ workspace }), approvals] });

To turn it on for some conversations only, leave it out of defineAgent, call registry.install(approvals), then conversation.configure({ extensions: { add: [approvals] } }) (and remove to turn it off).

Gate a tool you define with requireApproval(tool, { summarize, when? }):

tools: [requireApproval(cancelOrder, { summarize: args => `Cancel order ${args.number}` })]

The chat transport must accept answers, or the card cannot be answered. Return answer from its authenticate:

import { answerUserQuestion } from '@hachej/boring-agent/ask-user';
return { conversation, context, abortSubmission, answer: (callId, answer) => answerUserQuestion(conversation, callId, answer, context) };

The page passes chat.actions from useRemoteChat to the chat (see the build-agent-app page template).

Gate safely

  • Gate every tool that changes something: writes, deletes, sends, payments, external calls with effects. Reads stay ungated.
  • Gating only bash is not enough. Pi's write and edit change files without bash. Gate them too, or keep them out of the agent.
  • With selfEvolving: true, gating bash is bypassable. Agent-written tools in .agent/tools/*.json run their run command through the conversation's ExecutionEnv.exec, not through the bash tool, so a bash gate never sees them. The agent can write such a tool with write, call reload, then run any command. Gate write and edit (the way into .agent/), and choose an ExecutionEnv whose isolation you accept, because isolation is where exec runs (SELF-EVOLUTION.md).
  • Code mode: never expose a gated tool to a code-mode sandbox (run_code); its nested calls cannot reach a person. Give it read tools only and filter with isApprovalGated(tool).
  • Two approval extensions on one tool ask once; the first selected rule decides.
  • The check runs in host code inside the tool, so the model cannot skip it. The summarize text is what the person approves: make it name the effect.

Questions

import { createAskUserTool } from '@hachej/boring-agent/ask-user';
tools: [createAskUserTool()]

ask_user({ question, options?, allowFreeText?, questions? }) waits durably for the person's answer and shows a question card. It needs the same answer wiring as approvals. Tell the agent in instructions when to ask instead of guessing. Details: Asking the person.

Sub-agents

Define the child with defineAgent, then list it in delegates. Each becomes a delegate-style tool; install(registry) installs the child too.

const researcher = defineAgent({ id: 'researcher', model, instructions: 'Read and summarise. Never write.', extensions: [readOnlyFiles] });
const writer = defineAgent({ id: 'writer', model, delegates: [{ agent: researcher, name: 'research' }], extensions: [fileTools] });

The child runs in its own conversation with only its own tools and returns its final text. Give children the narrowest tools. Gates on the parent do not apply to the child: gate the child's tools on the child.

Schedules

import { createScheduleExtension } from '@hachej/boring-agent/schedule';
defineAgent({ ..., extensions: [createScheduleExtension()] });

The agent gets schedule({ instruction, delaySeconds | at }), list_schedules() and cancel_schedule({ id }). A schedule is a Pi task that sleeps on the Harness clock and then submits the instruction to its conversation, so it survives restarts. Hosts schedule from code with addSchedule, cancelSchedule and listSchedules. On a host with one wake-up timer (a Durable Object alarm), use onDeadline and scheduledDeadline. Details: Sub-agents and schedules.

Dry runs (sandbox)

createSandboxExtension({ tools, flags? }) from /sandbox records calls to mutating tools instead of running them, and blocks any tool it does not name. Select it per conversation as the last wrap, after any approval extension, and check the order with assertSandboxLast(selected, sandbox) over the complete list you pass to conversation.configure({ extensions: selected }). See Approval gate.

Self-evolving agents

defineAgent({ ..., selfEvolving: true, workspace }) lets the agent keep instructions, skills and tools in .agent/ and apply them with reload. Off by default. Agent-written code only runs through the conversation's ExecutionEnv; never import or eval workspace content in the host. Read the gating rules above before turning it on.

Rules

  • Capabilities are host code. The model only calls what you registered.
  • Credentials stay in execute, resolved per call. Never put them in instructions or tool output.
  • Fictional data in prompts, seeds and tests.

Verify

  1. node server.mjs starts and agent.install(registry) throws nothing (a duplicate tool or extension name throws).
  2. Ask the agent to change something gated: an approval card appears, Deny leaves the file or record unchanged, Approve runs it once.
  3. With selfEvolving: true: ask the agent to add a tool in .agent/tools/. The write must ask for approval first.
  4. Ask a question that needs a choice: the question card appears and the answer resumes the turn.
  5. Restart the server with a pending approval or schedule: it is still pending afterwards.
  6. Repository tests that cover these: test/packages/agent-ask-user.test.mjs (approvals and questions), test/packages/agent-sandbox.test.mjs (sandbox order).

评价

还没有评价。欢迎分享你的使用感受。

评论

无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。

还没有评论。来写第一条吧。

提交后会立即公开。请勿填写邮箱、电话等个人信息。URL 最多 2 个。

0 / 1000 字

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

同一仓库的技能

Find, install, update, check and theme Boring UI registry blocks (shadcn items such as pi-chat, pi-ambient, pi-workspace, pi-app, app-shell, viewers, file-tree, documents, feedback, windows) with the boring-ui-blocks command. Use when asked to "add a chat/agent block", "install pi-app", "upgrade/update the Boring blocks", "boring-ui-blocks check fails", "blocks edited", "restyle/rebrand the agent UI", "change the chat labels/icons/actions", "dark mode for the chat", or when tempted to edit a file under src/components/pi-*.

中文简介正在准备中。当前显示原文说明。

hachej/boring-ui492026年10月23日 更新

boring-pm

免费

The domain expert's product manager in a project repository run by the Boring Factory. Use when the expert brings a need or an idea, wants to clarify, change or resume a feature ("reprends la fiche"), asks what is happening with a feature, has a builder's question to answer, or has a preview to try and accept. Interviews one question at a time, writes the contract and mockups on the contract pull request, and submits the expert's approval only after the expert confirms. Never writes code.

中文简介正在准备中。当前显示原文说明。

hachej/boring-ui492026年10月23日 更新

boring-ui

免费

Entry point for building with Boring UI (the @hachej/boring-* npm packages and shadcn registry blocks for apps with an AI agent inside, on the Pi agent harness). Use when a task mentions boring-ui, @hachej/boring-ui-kit, @hachej/boring-agent, @hachej/boring-files, boring-ui-blocks, PiChat, AgentWorkspace, AmbientChat, AppShell, or asks to "add an agent/assistant/chat to my app", "build an app with an agent inside", or "use the Boring kit". Explains the packages, the rules every change must follow, and which boring-ui skill to load next.

中文简介正在准备中。当前显示原文说明。

hachej/boring-ui492026年10月23日 更新

Build a React + Node app with an AI agent inside using Boring UI, or add one to an existing app. Use when asked to "create an agent app", "add an AI assistant/chat/copilot to my app", "scaffold a Boring UI app", "wire AgentWorkspace/PiChat to a server", "set up the Pi Harness with the kit", or to connect the pi-app, pi-chat or pi-ambient blocks to defineAgent, createChatTransportHandler, createConversationsHandler and createRevisionHandler. Gives the verified smallest setup (one Node server, one page) and how to extend it.

中文简介正在准备中。当前显示原文说明。

hachej/boring-ui492026年10月23日 更新

查看 hachej 的全部技能

报告此技能的问题