跳到正文
cccskills
免费在 GitHub 公开

create-ai-tool

Build a new AI tool end-to-end — Rust implementation, toolset wiring, infra, schema generation, and frontend UI.

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

查看安装方法

包含的文件(1)

  • SKILL.md6.1 KB

SKILL.md(原文)

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

Create AI Tool

This skill walks through building a new AI tool from scratch. Before writing any code, read the design guide at crates/ai_toolset/TOOL_DESIGN.md and the framework docs/examples in crates/ai_toolset/src/lib.rs.

IMPORTANT: Never modify the crates/ai_toolset/ crate. It is the framework — you build tools that use it.

Step 1: Write the tool

Decide which domain crate the tool belongs in. Tools live at crates/<crate>/src/inbound/toolset/.

Study an existing tool for patterns:

  • crates/documents/src/inbound/toolset/ — tools: read_content.rs, read_metadata.rs, create_document.rs
  • crates/email/src/inbound/toolset/ — tools: send_email.rs, get_thread.rs, update_thread_labels.rs
  • crates/soup/src/inbound/toolset/ — tool: list_entities.rs
  • crates/call/src/inbound/toolset/ — call-related tools

Each tool is a struct that derives JsonSchema and Deserialize, with #[schemars(title = "...", description = "...")] on the struct and #[schemars(description = "...")] on each field. The struct implements AsyncTool<Context> from the ai_toolset crate.

Create a new file for your tool (e.g. my_tool.rs), add it as a mod in the toolset's mod.rs, and wire it into the toolset's AsyncToolSet::new().add_tool::<...>() chain.

Step 2: Create the tool context

If your tool needs dependencies (DB connections, service clients) that aren't already in an existing context, define a new context struct in the toolset's mod.rs. See crates/documents/src/inbound/toolset/mod.rs for the DocumentToolContext pattern.

The context must be Clone and derivable from the parent ToolServiceContext via FromRef.

If the tool's dependencies are already available in an existing context (e.g. it only needs Arc<ToolScribe>), you can use that context directly — no new struct needed.

Step 3: Add the toolset to all_tools in the ai_tools crate

Edit crates/ai_tools/src/lib.rs:

  • Import your toolset function and context type
  • Add .add_tool::<YourTool, YourContext>() or .add_subtoolset::<YourToolContext>(your_toolset()) to the all_tools() function

Step 4: Add the context to ToolServiceContext

Edit crates/ai_tools/src/tool_context.rs:

  • Add any new type aliases for your service implementations (follow the Tool* naming pattern)
  • Add your tool context field to the ToolServiceContext struct
  • Implement FromRef<ToolServiceContext> for your context if needed (or derive it — the struct uses #[derive(FromRef)])

Step 5: Wire up env vars and service construction

Edit crates/ai_tools/src/build_context.rs:

  • Add any new env vars to the env_var! or maybe_env_var! blocks
  • Construct your service/context in build_tool_service_context_from_env
  • Add it to the returned ToolServiceContext

Step 6: Update infra (if new env vars or AWS resources are needed)

Edit infra/packages/shared/src/ai_tools.ts:

  • Add new env vars to the envVars array in getAiToolsInfra()
  • Add any new secret ARNs, queue ARNs, or bucket ARNs to the respective arrays
  • Add any new Pulumi stack references needed to resolve the values

Step 7: Rust checks

Run from the repository root:

cargo fmt
cargo clippy -p ai_tools
cargo test -p <your_domain_crate>

Fix any warnings or errors before proceeding.

Step 8: Generate frontend types

Run from apps/web/:

bun gen-tools

This builds crates/ai_tools/src/bin/gen_tool_schemas.rs, generates crates/ai_tools/schemas/tools.json, and transpiles the schemas into TypeScript at apps/web/src/lib/service-clients/service-cognition/generated/tools/.

Step 9: Check what frontend UI is needed

Run from apps/web/:

bun check

This runs tsc --noEmit and will report type errors — specifically, the toolHandlers map in apps/web/src/lib/core/component/AI/component/tool/handler.tsx will be missing your new tool name. The errors tell you exactly what to implement.

Step 10: Read existing tool UI for patterns

The tool UI components live at apps/web/src/lib/core/component/AI/component/tool/. Study existing renderers:

  • Search.tsx — search results rendering
  • ReadContent.tsx / ReadMetadata.tsx — document tool UI
  • SendEmail.tsx — email tool UI
  • ListEntities.tsx — list display
  • Properties.tsx — property get/set tools
  • ListCallRecords.tsx / ReadCallRecord.tsx — call tools
  • BaseTool.tsx — shared base component

Each tool needs a handler object implementing ToolHandler (from ToolRenderer.tsx) with at minimum a render component. Use createToolRenderer to create it.

Step 11: Write the tool UI

  1. Create a new component file at apps/web/src/lib/core/component/AI/component/tool/YourTool.tsx
  2. Export a handler using createToolRenderer
  3. Register it in apps/web/src/lib/core/component/AI/component/tool/handler.tsx:
    • Import your handler
    • Add it to the toolHandlers map with the key matching your tool's schema title

Every tool renderer must show results. Use the expandable dropdown pattern from Search.tsx / ListEntities.tsx:

  • Use BaseTool (from BaseTool.tsx) as the wrapper. It accepts a response prop for expandable content.
  • Create const [isExpanded, setIsExpanded] = createSignal(false) to track open/closed state.
  • Access the response via ctx.response?.data (typed from the generated schema).
  • Show a status summary (e.g. hit count, "No Results") on the right side of the tool row.
  • Render a CaretRight toggle button (@icon/regular/caret-right.svg?component-solid) that rotates 90deg when expanded.
  • Pass the expanded content into BaseTool's response prop, gated on isExpanded().

For tools that return text/string results (not entity lists), render the response string in a <pre> or similar block inside the response prop. The key point: the response data must always be surfaced in the UI via the dropdown — never silently swallowed.

Step 12: Frontend checks

Run from apps/web/:

bun format
bun check

Fix any remaining type or formatting errors.

评价

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

评论

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

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

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

0 / 1000 字

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

同一仓库的技能

Wrap a new backend endpoint in the TypeScript SDK (packages/sdk), or record it as skipped. Use when `just coverage` fails, or after adding an endpoint to a Rust service.

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

macro-inc/macro47432026年10月19日 更新

add-tour

免费

Add or change an in-app feature tour (a view's guided flyover) in the web app. Use when adding a tour to a view, adding or editing tour steps, pointing a step at a new control, or when a step's target needs something opened first.

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

macro-inc/macro47432026年10月19日 更新

audit

免费

Post-change checks before handing off. Works out which checks apply from the files changed (directory AGENTS.md Checks sections and matching .agents/rules), runs or verifies each, and reports pass/fail/skipped. Use before saying work is done, before pushing, or when asked to audit or verify a change.

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

macro-inc/macro47432026年10月19日 更新

Enforce hexagonal architecture in the Rust backend. Use before modifying crates/ or Rust services, especially inbound axum/tool/listener adapters, domain services/ports, outbound adapters, authorization, permissions, database access, or external clients.

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

macro-inc/macro47432026年10月19日 更新

Use when adding collaborative markdown, notes, or descriptions to a feature with collab surfaces. Covers parent entities, service entry points, authorization, content storage, and lifecycle.

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

macro-inc/macro47432026年10月19日 更新

Use when building a feature on reusable database storage or UI, such as CRM, or deciding whether it needs a Macro database entity. Covers shared storage, a host-independent database UI and API contract, ownership, authorization, and the _entities naming convention.

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

macro-inc/macro47432026年10月19日 更新

查看 macro-inc 的全部技能

报告此技能的问题