一键导入
add-tool
Create a custom user tool in ~/.ntrp/tools/ using the current tool(...) API.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Create a custom user tool in ~/.ntrp/tools/ using the current tool(...) API.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Use this skill when the user wants a memory feed — a scheduled automation that fetches targeted data from their integrations (gmail/calendar/slack/web) and keeps ONE memory page current, updated in place. Examples; "track my PR queue", "keep an invoices page", "week-ahead brief".
Implement a spec end-to-end — recon readers map the codebase, an architect pins every cross-file contract in a blueprint, parallel builders implement disjoint workstreams from it, adversarial review, then a final test gate. Use for multi-file feature work. Run via the workflow tool by name.
Find -> adversarially verify -> rank issues over a target (a diff, dir, file, or glob). Use for code review, a scoped bug hunt, a security or perf pass. Run via the workflow tool by name.
Answer a question about a target by fanning out parallel readers over derived angles, then synthesizing a cited answer. Use to understand a subsystem, research a question, or trace how/where something works. Run via the workflow tool by name.
Decide between approaches — generate N diverse proposals from different lenses, score each against criteria with independent judges, then synthesize a decisive recommendation. Use for design choices, tradeoff calls, "which approach should we take". Run via the workflow tool by name.
Use this skill when the user wants to turn the current conversation into a scheduled automation. Analyze the session and call create_automation to propose one — the user reviews the full prompt + schedule in the approval card before it's saved.
| name | add-tool |
| description | Create a custom user tool in ~/.ntrp/tools/ using the current tool(...) API. |
Help the user create a custom tool. User tools live in ~/.ntrp/tools/ as Python files and are discovered when the server starts.
Important: Use bash to run the scaffold script and apply edits. Use read_file to read and verify. Do not create class-based tools. The only supported user-tool registration shape is a module-level tools: dict[str, Tool] built with tool(...).
Ask the user:
policy.requires_approval=True, needs an approval function)Run the scaffold script (path is relative to the path attribute from the <skill> tag above):
bash <skill_path>/scripts/scaffold.sh <tool_name>
This creates ~/.ntrp/tools/<tool_name>.py from the current tool(...) template.
Use read_file on ~/.ntrp/tools/<tool_name>.py, then use bash to apply edits:
ToolInput and execute_tool if clearerdisplay_name and descriptionToolInput fields to match the user's parametersToolPolicy.action and ToolPolicy.scope to match the tool behaviorrequires_approval=True, uncomment and implement the approval function, then pass it as approval=...permissions=frozenset({...}) and service access (see patterns below)tools = {"tool_name": tool(...)} mappingfrom pydantic import BaseModel, Field
from ntrp.tools.core import ToolAction, ToolPolicy, ToolResult, ToolScope, tool
from ntrp.tools.core.context import ToolExecution
class MyInput(BaseModel):
query: str = Field(description="Search query")
async def my_tool(execution: ToolExecution, args: MyInput) -> ToolResult:
return ToolResult(content=args.query, preview="Done")
tools = {
"my_tool": tool(
display_name="MyTool",
description="Describe when the agent should use this tool.",
input_model=MyInput,
policy=ToolPolicy(action=ToolAction.READ, scope=ToolScope.INTERNAL),
execute=my_tool,
)
}
The execute function must return ToolResult. Returning a string, dict, or arbitrary object is invalid.
from ntrp.integrations.slack.client import SlackClient
async def search_slack(execution: ToolExecution, args: MyInput) -> ToolResult:
client = execution.ctx.get_client("slack", SlackClient)
if client is None:
return ToolResult(content="Slack is not configured.", preview="Missing service", is_error=True)
results = await client.search_messages(args.query)
lines = [f"{item.title}: {item.content}" for item in results]
return ToolResult(content="\n".join(lines), preview=f"{len(results)} results")
tools = {
"search_slack": tool(
description="Search Slack messages.",
input_model=MyInput,
policy=ToolPolicy(
action=ToolAction.READ,
scope=ToolScope.EXTERNAL,
permissions=frozenset({"slack"}),
),
execute=search_slack,
)
}
async def recall_memory(execution: ToolExecution, args: MyInput) -> ToolResult:
memory = execution.ctx.services["memory"]
Keys for policy.permissions and execution.ctx.services:
| Key | Type | What it provides |
|---|---|---|
gmail | MultiGmailSource | Email read/search/send |
calendar | MultiCalendarSource | Calendar events CRUD |
web | WebClient | Web search and content fetch |
memory | MemoryService | Long-term memory service |
automation | AutomationService | Scheduled automation management |
skill_registry | SkillRegistry | Skill lookup and loading |
search_index | SearchIndex | Vector search across indexed sources |
slack | SlackClient | Slack search/read APIs |
mcp | MCPManager | Connected MCP tools |
notifiers | NotifierService | Configured notifiers |
Use execution.ctx.get_client("service_id", ClientType) for integration clients when you can import the concrete client type. Use execution.ctx.services["key"] for internal services such as memory and automation.
tool(...) arguments| Argument | Required | Description |
|---|---|---|
description | yes | The LLM reads this to decide when to call the tool |
execute | yes | Async function receiving (ToolExecution, args) and returning ToolResult |
display_name | no | Shown in the UI |
input_model | no | Pydantic BaseModel; omitted means no parameters |
policy | yes | ToolPolicy(action=..., scope=..., ...); controls visibility, approval, audit, and result handling |
approval | no | Async function returning `ApprovalInfo |
Policy fields:
| Field | Description |
|---|---|
action | READ, DRAFT, WRITE, or EXECUTE |
scope | INTERNAL for ntrp/local state, EXTERNAL for third-party systems |
requires_approval | True pauses for user approval before execution |
permissions | Service keys; tool is hidden when any is missing |
timeout_seconds | Optional per-tool execution timeout |
audit | Whether calls should be auditable |
max_result_chars | Optional context result limit |
offload | Whether large results can be offloaded to a reference |
read_file to verify the final tool filentrp-server serve) for discoverytool(...) API as built-in toolsuv pip install ...)tools mapping