[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6MMEGBCZ1TRRHDGE6W1RTHF":3,"skill-same:01M6MMEGBCZ1TRRHDGE6W1RTHF":91},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":34,"publishedAt":55,"linkOnly":56,"markdownContent":57,"markdownBody":58,"frontMatter":59,"refName":62,"commitSha":63,"skillDirectory":64,"forksCount":65,"repositoryHtmlUrl":66,"repositoryHomepageUrl":67,"ownerHtmlUrl":68,"ownerBlogUrl":69,"ownerDescription":70,"updatedAt":71,"install":72,"resources":84},"01M6MMEGBCZ1TRRHDGE6W1RTHF","tool-design-security",null,"Design or audit a tool's trust boundary: keep API keys and tenant ids out of model-visible parameters, resist prompt injection, enforce permissions and approval gates in code, declare scopes, and log calls safely.","hashgraph-online\u002Fawesome-codex-plugins","hashgraph-online","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F160371962?v=4","01M6CNB6NRJVNNGN14TR01Q6D3","HOL (Hashgraph Online)","01M6JT1HSKKG9V68KQAQGBA7XP",1559,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Fruntypelabs\u002Fskills\u002Fskills\u002Ftool-design-security\u002FSKILL.md",[18,23,26,31],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000015","视觉设计","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",{"categoryNo":27,"categoryName":28,"taxonomyType":29,"taxonomyTypeDesc":30},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",{"categoryNo":32,"categoryName":33,"taxonomyType":29,"taxonomyTypeDesc":30},"01JBSEEDCAT000000000000032","设计师",[35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54],"tool design security","security","design security","tool","design","tool design","model","trust boundary","tenant","api keys","enforce","trust","log","api","injection","ids","audit","permissions","code","prompt injection","2026-11-10 10:12:30",false,"---\nname: tool-design-security\ndescription: \"Design or audit a tool's trust boundary: keep API keys and tenant ids out of model-visible parameters, resist prompt injection, enforce permissions and approval gates in code, declare scopes, and log calls safely.\"\nuser-invocable: true\nargument-hint: '[tool or toolkit whose trust boundary to design]'\n---\n\n# Tool Security and Context Design\n\nPrompts express intent; code enforces rules. An agent under prompt injection will try\nto call the wrong tool with the wrong arguments and will produce a persuasive reason\nfor doing so. The only defenses that hold are the ones the tool layer enforces without\nconsulting the model.\n\n## Procedure\n\n1. **Name the principal.** Who is the tool acting as: a user, a service account, an\n   organization? Where does that identity come from (session, token, context object)?\n2. **Route every credential through injection.** No secret, token, or key is ever a\n   model-visible parameter.\n3. **Write the permission check in code**, before the operation, for both the action\n   (\"can this principal delete users\") and the target (\"this user, in this org\").\n4. **Declare scopes** per tool and pre-check them.\n5. **Fix the boundary**: tenant, root path, allowed hosts, quotas.\n6. **Log every invocation** with redacted parameters.\n7. **Decide what context to inject** automatically (team, timezone, environment) and\n   what the agent must establish itself through an identity anchor.\n\n## Rules with examples\n\n### Secrets never pass through the model (Secret Injection)\n\nBefore (the key is in the schema, so it is in the prompt, the trace, and the transcript):\n\n```json\n{\n  \"name\": \"call_api\",\n  \"parameters\": { \"apiKey\": { \"type\": \"string\" }, \"endpoint\": { \"type\": \"string\" } }\n}\n```\n\nAfter (the key is resolved from server-side context at execution, and the host is fixed\nin config so the model cannot send the credential anywhere else):\n\n```json\n{\n  \"name\": \"call_api\",\n  \"parameters\": { \"resource\": { \"type\": \"string\", \"enum\": [\"orders\", \"invoices\"] } },\n  \"config\": {\n    \"url\": \"https:\u002F\u002Fapi.example.com\u002F{{resource}}\",\n    \"headers\": { \"Authorization\": \"Bearer {{secret:SERVICE_API_KEY}}\" }\n  }\n}\n```\n\nStore credentials encrypted at rest, resolve them at call time, log the access, and\nnever log or return the value. If a parameter's only purpose is to carry a credential\nor a trust decision, it is not a parameter.\n\n### Access control lives in code (Permission Gate)\n\nCheck permissions at the top of execution, on the principal from context, not from any\nargument the model supplied. Check the action and the target. Deny with a `permanent`\nerror that names the required role, and log every denial. Re-authenticating does not\nfix a missing role, so reserve `authRequired` for a missing or expired credential or scope.\n\n```text\nif \"admin\" not in principal.roles: deny(required=\"admin\")\nif target.orgId != principal.orgId: deny(reason=\"outside your organization\")\n```\n\nA system prompt that says \"never delete users\" is a UX hint, not a control. Approval\ngates on destructive or costly commands are a backstop for residual risk, not a\nsubstitute for least-privilege tool selection; gate the few dangerous calls, not\neverything, or the human learns to rubber-stamp.\n\n### Declare the scopes each tool needs (Scope Declaration)\n\nList the minimum required scopes and any optional ones in the tool definition and in\nthe description (\"Requires `gmail.send`\"). Pre-check before the upstream call and return\nan `authRequired` error that names the missing scope and how to re-authenticate. Use\nthe narrowest scope that works; different tools in the same set can require different\nscopes.\n\n### Every call is logged (Audit Trail)\n\nRecord what (tool name, parameters with secrets and PII redacted), who (principal,\nsession), when, and the result (success or failure, duration, error class). Set a\nretention period. This is how abuse is detected and how \"why did the agent do that\" is\nanswered later.\n\n### The agent can ask who it is (Identity Anchor)\n\nProvide a `who_am_i` discovery tool that returns the principal's id, name, roles,\npermissions, and team or organization, and either recommend it as the first call in\ntool descriptions or run it automatically and inject the result into the system prompt.\nCache it for the session. Downstream tools reference the ids it returns.\n\n### State across calls is explicit (Session Context)\n\nWhen tools share working state (current project, selected account, scope), store it\nserver-side against the session, expose tools to set and read it, expire stale sessions,\nand echo the active context in results so the agent and the user can see what scope a\ncall ran in.\n\n### Inject what the agent would not think to ask for (Context Injection)\n\nPresentation context (timezone, locale, region) is supplied from context by default and\nmay be overridden by explicit parameters. Feature flags, entitlements, and authorization\nscope (team, organization, tenant) are also injected from context, but the model can\nnever override them: a tool that needs to act on another team resolves that through the\npermission gate, not through a parameter. Document what is injected, return the\neffective values in the response, and expand machine ids to names where a human will\nread the result.\n\n### Boundaries are enforced, not described (Context Boundary)\n\nFile tools resolve every path against a root and refuse anything outside it. Data tools\ncarry a tenant scope from context and never accept one from the model. Network tools\ncheck hosts against an allowlist. Quotas and rate limits are applied in the tool layer.\nViolations return a clear, logged error.\n\n## Anti-patterns\n\n- `apiKey`, `token`, `tenantId`, or `actAsUserId` as model-visible parameters.\n- Authorization decided by reading the agent's stated reason for a call.\n- Permission rules that exist only in the system prompt.\n- A file tool that joins a user-supplied path without checking it stays under the root.\n- Logging full parameters, including the secret that was injected.\n- One broad OAuth scope for the whole server because it was easier.\n\n## On Runtype\n\n- **Principal.** Your server passes `tenant: { id }` and `endUser: { id }` on dispatch or\n  agent execute. Tools read them as `{{_tenant.id}}` and `{{_endUser.id}}`, next to\n  `{{_user.id}}` for your own account. A plain `tenant` or `endUser` value is asserted by\n  the caller, so set it only from a trusted server, never from a model argument. From a\n  browser, or to prove who the user is, send `identityProof` instead, and set\n  `config.tenancyStrategy` on the saved agent to require that identity. Use `.id`, not\n  `.projectedId`.\n- **Principal your API can verify.** When your API must check the identity itself, put\n  `Authorization: Bearer {{_identity.token}}` on an `external` tool (or an inline MCP\n  server header). Runtype signs a five-minute ES256 JWT per call with `aud` = the tool's\n  fixed host and `iss` = `https:\u002F\u002Fapi.runtype.com\u002Forgs\u002F\u003CorganizationId>`; the model never\n  sees it. It is minted only for an agent with `tenancyStrategy` and a resolved identity.\n  The receiver must verify against `https:\u002F\u002Fapi.runtype.com\u002F.well-known\u002Fjwks.json` and pin\n  `iss` to its own customer's org, because every org shares the signing key.\n- **Secrets.** `{{secret:KEY}}` references resolve from the managed secret store at\n  execution and are the only credential contract. They resolve in `external` tool\n  `url`, `headers`, `body`, and auth; in the HTTP flow steps (`fetch-url`, `api-call`,\n  `wait-until`, `paginate-api`); and in custom MCP server auth (`token`, `username`,\n  `password`, `headers` values, and OAuth client credentials). They do not resolve in\n  prompts, code, or a saved MCP tool's config. Full list:\n  https:\u002F\u002Fdocs.runtype.com\u002Fuser-guide\u002Fsettings\u002Fmanaging-secrets\n  - A runtime tool of any other type (`custom`, `flow`, `local`) that contains a secret\n    reference is rejected with 400. Move the credential into an `external` tool.\n  - An API key that dispatches runtime tools with secret references needs `SECRETS:READ`\n    (or `SECRETS:*`), or the request fails with 403.\n  - Before a run, call `check_secrets` with the referenced keys to confirm none is\n    missing or revoked.\n  - Never collect secret values in chat. Hand users the dashboard intake URL from\n    `get_secret_intake_manifest`, and create pending secrets with `create_secret` (no\n    `value`) so the reference resolves once the owner fills it in.\n- **Context injection.** `hiddenParameterNames` on a runtime tool (the same field in the\n  API, SDK, and product definitions) removes those parameters from the schema the model\n  sees and fills them from execution variables or `_record.metadata`. Names that start\n  with `_internal` are rejected.\n- **Least privilege.** Enable only the tools the agent needs in `toolIds`. On a custom\n  MCP server, set `allowedTools` so the model sees only the listed tools, not the\n  server's whole catalog.\n- **Local tools.** A `local` tool runs in the caller's client (SDK or Persona), outside\n  your server. Put no credentials or authorization decisions in it, and treat its result\n  as untrusted input. Enforce permissions in an `external` tool or your own backend.\n- **Boundaries.** Cap calls with `tools.maxToolCalls` (1 to 100 per execution) and bound\n  the loop with `loopConfig.maxTurns` or `loopConfig.maxCost`. For expensive or\n  destructive tools, enforce a per-tool budget inside the tool; do not set\n  `tools.perToolLimits`, which is retired and gets the agent rejected. Runtype caps a\n  request's serialized `runtimeTools` at 1 MB and does not cap the tool count, so a\n  smaller tool set is not an injection defense. Pin the host in an external tool's `url`\n  instead of accepting it as a parameter.\n- **Permission gate.** `config.tools.approval` pauses gated tool calls for a human:\n  - `require` takes tool names or patterns (`mcp:*`, `builtin:*`), or `true` for every\n    tool. Prefer the list.\n  - `timeout` is in milliseconds (default 300000, five minutes).\n  - `requestReason` (on by default) asks the model for a justification, carried as the\n    reserved `_approvalReason` parameter. The reason is display-only and must never\n    drive the decision.\n  - `choices` (`alwaysAllow`, `alwaysDeny`, both off by default) offers persistent\n    decisions at the prompt. List remembered grants with\n    `GET \u002Fv1\u002Ftool-approval-grants?agentId=` and revoke one with\n    `DELETE \u002Fv1\u002Ftool-approval-grants\u002F{id}`. Review them when you tighten a tool.\n  - The approver answers with `POST \u002Fv1\u002Fdispatch\u002Fapprove` (or\n    `POST \u002Fv1\u002Fagents\u002F{id}\u002Fapprove` for a saved agent).\n  - Approval needs someone to answer it. API dispatch and agent execute wait for the\n    approve call, and Slack, Telegram, SMS, and iMessage surfaces running a multi-turn\n    agent collect the decision in the conversation. Client-token (Persona) chat and\n    product chat refuse approval-gated agents with 501 `APPROVAL_MODE_UNSUPPORTED`,\n    except a root gate with `tools.approval.approver: \"end-user\"`, which the Persona\n    visitor approves in the widget. Use `end-user` only when the gate asks for the\n    visitor's own consent (confirming their order, booking, or message). Keep\n    `owner` for gates that enforce your policy or budget (refunds, discounts,\n    credits, spend on your account): the visitor must not grant those to themselves.\n    Email, schedule, webhook, Discord, and WhatsApp surfaces cannot collect a decision,\n    and neither can Slack, Telegram, SMS, or iMessage for a single-pass agent. Watch\n    for the `APPROVAL_UNANSWERABLE_ON_SURFACE` warning when you save an agent or bind it\n    to a surface; on those surfaces, remove the gate and enforce the rule in the tool.\n  - Approval covers only tool calls a model chooses in an agent or a prompt step. A flow\n    Tool Call step has no approval gate and always runs.\n- **Session context.** Keep per-conversation working state (current project, selected\n  account) in the conversation's messages or variables, or in a record keyed by\n  conversation. Use memory (`save_memory` \u002F `recall_memory`, enabled with\n  `config.memory.enabled`) only for facts and preferences that must survive across\n  sessions, and scope it with `config.memory.profileTemplate` (for example\n  `{{_endUser.id}}`) so one end user's state never reaches another. An agent with a\n  `tenancyStrategy` ignores `profileTemplate` and scopes memory to the tenant and end\n  user itself.\n- **Audit.** Every tool call is traced on the run (`trace_execution`, `list_logs`).\n  Values of parameters listed in `hiddenParameterNames` are redacted in tool-input\n  events; every other argument is recorded as sent, so keep PII and secrets out of\n  model-visible parameters and results.\n- Read `get_platform_documentation(topic=\"agent-design\")` for the approval-gate\n  contract and `get_platform_documentation(topic=\"external-tools\")` for the secret\n  syntax rules.\n","# Tool Security and Context Design\n\nPrompts express intent; code enforces rules. An agent under prompt injection will try\nto call the wrong tool with the wrong arguments and will produce a persuasive reason\nfor doing so. The only defenses that hold are the ones the tool layer enforces without\nconsulting the model.\n\n## Procedure\n\n1. **Name the principal.** Who is the tool acting as: a user, a service account, an\n   organization? Where does that identity come from (session, token, context object)?\n2. **Route every credential through injection.** No secret, token, or key is ever a\n   model-visible parameter.\n3. **Write the permission check in code**, before the operation, for both the action\n   (\"can this principal delete users\") and the target (\"this user, in this org\").\n4. **Declare scopes** per tool and pre-check them.\n5. **Fix the boundary**: tenant, root path, allowed hosts, quotas.\n6. **Log every invocation** with redacted parameters.\n7. **Decide what context to inject** automatically (team, timezone, environment) and\n   what the agent must establish itself through an identity anchor.\n\n## Rules with examples\n\n### Secrets never pass through the model (Secret Injection)\n\nBefore (the key is in the schema, so it is in the prompt, the trace, and the transcript):\n\n```json\n{\n  \"name\": \"call_api\",\n  \"parameters\": { \"apiKey\": { \"type\": \"string\" }, \"endpoint\": { \"type\": \"string\" } }\n}\n```\n\nAfter (the key is resolved from server-side context at execution, and the host is fixed\nin config so the model cannot send the credential anywhere else):\n\n```json\n{\n  \"name\": \"call_api\",\n  \"parameters\": { \"resource\": { \"type\": \"string\", \"enum\": [\"orders\", \"invoices\"] } },\n  \"config\": {\n    \"url\": \"https:\u002F\u002Fapi.example.com\u002F{{resource}}\",\n    \"headers\": { \"Authorization\": \"Bearer {{secret:SERVICE_API_KEY}}\" }\n  }\n}\n```\n\nStore credentials encrypted at rest, resolve them at call time, log the access, and\nnever log or return the value. If a parameter's only purpose is to carry a credential\nor a trust decision, it is not a parameter.\n\n### Access control lives in code (Permission Gate)\n\nCheck permissions at the top of execution, on the principal from context, not from any\nargument the model supplied. Check the action and the target. Deny with a `permanent`\nerror that names the required role, and log every denial. Re-authenticating does not\nfix a missing role, so reserve `authRequired` for a missing or expired credential or scope.\n\n```text\nif \"admin\" not in principal.roles: deny(required=\"admin\")\nif target.orgId != principal.orgId: deny(reason=\"outside your organization\")\n```\n\nA system prompt that says \"never delete users\" is a UX hint, not a control. Approval\ngates on destructive or costly commands are a backstop for residual risk, not a\nsubstitute for least-privilege tool selection; gate the few dangerous calls, not\neverything, or the human learns to rubber-stamp.\n\n### Declare the scopes each tool needs (Scope Declaration)\n\nList the minimum required scopes and any optional ones in the tool definition and in\nthe description (\"Requires `gmail.send`\"). Pre-check before the upstream call and return\nan `authRequired` error that names the missing scope and how to re-authenticate. Use\nthe narrowest scope that works; different tools in the same set can require different\nscopes.\n\n### Every call is logged (Audit Trail)\n\nRecord what (tool name, parameters with secrets and PII redacted), who (principal,\nsession), when, and the result (success or failure, duration, error class). Set a\nretention period. This is how abuse is detected and how \"why did the agent do that\" is\nanswered later.\n\n### The agent can ask who it is (Identity Anchor)\n\nProvide a `who_am_i` discovery tool that returns the principal's id, name, roles,\npermissions, and team or organization, and either recommend it as the first call in\ntool descriptions or run it automatically and inject the result into the system prompt.\nCache it for the session. Downstream tools reference the ids it returns.\n\n### State across calls is explicit (Session Context)\n\nWhen tools share working state (current project, selected account, scope), store it\nserver-side against the session, expose tools to set and read it, expire stale sessions,\nand echo the active context in results so the agent and the user can see what scope a\ncall ran in.\n\n### Inject what the agent would not think to ask for (Context Injection)\n\nPresentation context (timezone, locale, region) is supplied from context by default and\nmay be overridden by explicit parameters. Feature flags, entitlements, and authorization\nscope (team, organization, tenant) are also injected from context, but the model can\nnever override them: a tool that needs to act on another team resolves that through the\npermission gate, not through a parameter. Document what is injected, return the\neffective values in the response, and expand machine ids to names where a human will\nread the result.\n\n### Boundaries are enforced, not described (Context Boundary)\n\nFile tools resolve every path against a root and refuse anything outside it. Data tools\ncarry a tenant scope from context and never accept one from the model. Network tools\ncheck hosts against an allowlist. Quotas and rate limits are applied in the tool layer.\nViolations return a clear, logged error.\n\n## Anti-patterns\n\n- `apiKey`, `token`, `tenantId`, or `actAsUserId` as model-visible parameters.\n- Authorization decided by reading the agent's stated reason for a call.\n- Permission rules that exist only in the system prompt.\n- A file tool that joins a user-supplied path without checking it stays under the root.\n- Logging full parameters, including the secret that was injected.\n- One broad OAuth scope for the whole server because it was easier.\n\n## On Runtype\n\n- **Principal.** Your server passes `tenant: { id }` and `endUser: { id }` on dispatch or\n  agent execute. Tools read them as `{{_tenant.id}}` and `{{_endUser.id}}`, next to\n  `{{_user.id}}` for your own account. A plain `tenant` or `endUser` value is asserted by\n  the caller, so set it only from a trusted server, never from a model argument. From a\n  browser, or to prove who the user is, send `identityProof` instead, and set\n  `config.tenancyStrategy` on the saved agent to require that identity. Use `.id`, not\n  `.projectedId`.\n- **Principal your API can verify.** When your API must check the identity itself, put\n  `Authorization: Bearer {{_identity.token}}` on an `external` tool (or an inline MCP\n  server header). Runtype signs a five-minute ES256 JWT per call with `aud` = the tool's\n  fixed host and `iss` = `https:\u002F\u002Fapi.runtype.com\u002Forgs\u002F\u003CorganizationId>`; the model never\n  sees it. It is minted only for an agent with `tenancyStrategy` and a resolved identity.\n  The receiver must verify against `https:\u002F\u002Fapi.runtype.com\u002F.well-known\u002Fjwks.json` and pin\n  `iss` to its own customer's org, because every org shares the signing key.\n- **Secrets.** `{{secret:KEY}}` references resolve from the managed secret store at\n  execution and are the only credential contract. They resolve in `external` tool\n  `url`, `headers`, `body`, and auth; in the HTTP flow steps (`fetch-url`, `api-call`,\n  `wait-until`, `paginate-api`); and in custom MCP server auth (`token`, `username`,\n  `password`, `headers` values, and OAuth client credentials). They do not resolve in\n  prompts, code, or a saved MCP tool's config. Full list:\n  https:\u002F\u002Fdocs.runtype.com\u002Fuser-guide\u002Fsettings\u002Fmanaging-secrets\n  - A runtime tool of any other type (`custom`, `flow`, `local`) that contains a secret\n    reference is rejected with 400. Move the credential into an `external` tool.\n  - An API key that dispatches runtime tools with secret references needs `SECRETS:READ`\n    (or `SECRETS:*`), or the request fails with 403.\n  - Before a run, call `check_secrets` with the referenced keys to confirm none is\n    missing or revoked.\n  - Never collect secret values in chat. Hand users the dashboard intake URL from\n    `get_secret_intake_manifest`, and create pending secrets with `create_secret` (no\n    `value`) so the reference resolves once the owner fills it in.\n- **Context injection.** `hiddenParameterNames` on a runtime tool (the same field in the\n  API, SDK, and product definitions) removes those parameters from the schema the model\n  sees and fills them from execution variables or `_record.metadata`. Names that start\n  with `_internal` are rejected.\n- **Least privilege.** Enable only the tools the agent needs in `toolIds`. On a custom\n  MCP server, set `allowedTools` so the model sees only the listed tools, not the\n  server's whole catalog.\n- **Local tools.** A `local` tool runs in the caller's client (SDK or Persona), outside\n  your server. Put no credentials or authorization decisions in it, and treat its result\n  as untrusted input. Enforce permissions in an `external` tool or your own backend.\n- **Boundaries.** Cap calls with `tools.maxToolCalls` (1 to 100 per execution) and bound\n  the loop with `loopConfig.maxTurns` or `loopConfig.maxCost`. For expensive or\n  destructive tools, enforce a per-tool budget inside the tool; do not set\n  `tools.perToolLimits`, which is retired and gets the agent rejected. Runtype caps a\n  request's serialized `runtimeTools` at 1 MB and does not cap the tool count, so a\n  smaller tool set is not an injection defense. Pin the host in an external tool's `url`\n  instead of accepting it as a parameter.\n- **Permission gate.** `config.tools.approval` pauses gated tool calls for a human:\n  - `require` takes tool names or patterns (`mcp:*`, `builtin:*`), or `true` for every\n    tool. Prefer the list.\n  - `timeout` is in milliseconds (default 300000, five minutes).\n  - `requestReason` (on by default) asks the model for a justification, carried as the\n    reserved `_approvalReason` parameter. The reason is display-only and must never\n    drive the decision.\n  - `choices` (`alwaysAllow`, `alwaysDeny`, both off by default) offers persistent\n    decisions at the prompt. List remembered grants with\n    `GET \u002Fv1\u002Ftool-approval-grants?agentId=` and revoke one with\n    `DELETE \u002Fv1\u002Ftool-approval-grants\u002F{id}`. Review them when you tighten a tool.\n  - The approver answers with `POST \u002Fv1\u002Fdispatch\u002Fapprove` (or\n    `POST \u002Fv1\u002Fagents\u002F{id}\u002Fapprove` for a saved agent).\n  - Approval needs someone to answer it. API dispatch and agent execute wait for the\n    approve call, and Slack, Telegram, SMS, and iMessage surfaces running a multi-turn\n    agent collect the decision in the conversation. Client-token (Persona) chat and\n    product chat refuse approval-gated agents with 501 `APPROVAL_MODE_UNSUPPORTED`,\n    except a root gate with `tools.approval.approver: \"end-user\"`, which the Persona\n    visitor approves in the widget. Use `end-user` only when the gate asks for the\n    visitor's own consent (confirming their order, booking, or message). Keep\n    `owner` for gates that enforce your policy or budget (refunds, discounts,\n    credits, spend on your account): the visitor must not grant those to themselves.\n    Email, schedule, webhook, Discord, and WhatsApp surfaces cannot collect a decision,\n    and neither can Slack, Telegram, SMS, or iMessage for a single-pass agent. Watch\n    for the `APPROVAL_UNANSWERABLE_ON_SURFACE` warning when you save an agent or bind it\n    to a surface; on those surfaces, remove the gate and enforce the rule in the tool.\n  - Approval covers only tool calls a model chooses in an agent or a prompt step. A flow\n    Tool Call step has no approval gate and always runs.\n- **Session context.** Keep per-conversation working state (current project, selected\n  account) in the conversation's messages or variables, or in a record keyed by\n  conversation. Use memory (`save_memory` \u002F `recall_memory`, enabled with\n  `config.memory.enabled`) only for facts and preferences that must survive across\n  sessions, and scope it with `config.memory.profileTemplate` (for example\n  `{{_endUser.id}}`) so one end user's state never reaches another. An agent with a\n  `tenancyStrategy` ignores `profileTemplate` and scopes memory to the tenant and end\n  user itself.\n- **Audit.** Every tool call is traced on the run (`trace_execution`, `list_logs`).\n  Values of parameters listed in `hiddenParameterNames` are redacted in tool-input\n  events; every other argument is recorded as sent, so keep PII and secrets out of\n  model-visible parameters and results.\n- Read `get_platform_documentation(topic=\"agent-design\")` for the approval-gate\n  contract and `get_platform_documentation(topic=\"external-tools\")` for the secret\n  syntax rules.\n",{"name":5,"description":7,"argument-hint":60,"user-invocable":61},"[tool or toolkit whose trust boundary to design]",true,"main","2b63f856ce19c2a797929cacabd9e0fc936812fa","plugins\u002Fruntypelabs\u002Fskills\u002Fskills\u002Ftool-design-security",474,"https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins","https:\u002F\u002Fhol.org\u002Fplugins\u002Fbest-codex-plugins","https:\u002F\u002Fgithub.com\u002Fhashgraph-online","https:\u002F\u002Fhol.org","Open-source standards and developer tools for interoperable AI agents: discovery, identity, communication, payments, privacy and security.","2026-11-11 14:40:14",{"source":8,"skillName":5,"commands":73,"prompt":83,"zipAvailable":61},[74,77,80],{"tool":75,"command":76},"npx","npx skills add hashgraph-online\u002Fawesome-codex-plugins --skill tool-design-security",{"tool":78,"command":79},"bunx","bunx skills add hashgraph-online\u002Fawesome-codex-plugins --skill tool-design-security",{"tool":81,"command":82},"pnpm","pnpm dlx skills add hashgraph-online\u002Fawesome-codex-plugins --skill tool-design-security","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Fruntypelabs\u002Fskills\u002Fskills\u002Ftool-design-security\u002FSKILL.md",[85],{"path":86,"resourceType":87,"resourceTypeDesc":88,"sizeBytes":89,"sourceHtmlUrl":90},"agents\u002Fopenai.yaml","REFERENCE","参考文档",310,"https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Fruntypelabs\u002Fskills\u002Fskills\u002Ftool-design-security\u002Fagents\u002Fopenai.yaml",[92,100,107,114,140,165],{"skillNo":93,"name":94,"nameZh":6,"description":95,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":96,"categories":97,"keywords":98,"publishedAt":99},"01M746ZWACVKMZ1BJXJZHYJSSX","migrate-to-e2e","Moves an existing Playwright, Cypress, Selenium, Appium, Detox, Maestro, or TesterArmy suite to e2e one slice at a time, with the old suite running beside the new one until each ported test is proven. Keeps a MIGRATION.md progress file so any later session resumes where the last stopped. Optionally plants a defect to show both suites catch it. Use for \u002Fmigrate-to-e2e, \"migrate our tests to e2e\", \"port these Maestro flows\", \"move our TesterArmy tests\", or when a project has an e2e config and an older suite still running.","https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Ftester-army\u002Fe2e\u002Fskills\u002Fmigrate-to-e2e\u002FSKILL.md",[],[],"2026-11-11 15:11:14",{"skillNo":101,"name":102,"nameZh":6,"description":103,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":104,"categories":105,"keywords":106,"publishedAt":99},"01M746ZPTAX1Q0FBKAB1CYND7E","e2e","Writes, runs, and debugs end-to-end tests for web and mobile apps with e2e, the agentic test runner, which mixes agent.act goals with exact locator assertions on a Playwright browser or an iOS or Android device. Also drives a project's running app live over the e2e MCP server to look at a screen, check a UI change, take a screenshot or record a video, and try a locator; and runs bug bashes, parallel e2e explore runs with each bug proven by a repro test. Use when a project depends on e2e or has an e2e.config.ts, when asked for end-to-end, browser, mobile, or agentic UI tests, to check a change in the running app, to QA or bug bash an app or branch, or when an e2e run fails.","https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Ftester-army\u002Fe2e\u002Fskills\u002Fe2e\u002FSKILL.md",[],[],{"skillNo":108,"name":109,"nameZh":6,"description":110,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":111,"categories":112,"keywords":113,"publishedAt":99},"01M746ZJN784HVHMDP9MQGCSGG","create-verification-skill","Generate a project-local verify-\u003Capp> skill on top of e2e, so any coding agent can launch the app, check it is worth driving, exercise a feature the way a user does, keep evidence, and bug bash it. Writes the skill, a feature map with one explore charter per feature, and proves it once. Use for \u002Fcreate-verification-skill, \"make a verification skill for this repo\", or when a project has no scripted way to prove UI behavior.","https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Ftester-army\u002Fe2e\u002Fskills\u002Fcreate-verification-skill\u002FSKILL.md",[],[],{"skillNo":115,"name":116,"nameZh":6,"description":117,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":118,"categories":119,"keywords":120,"publishedAt":55},"01M716A6ETNB9B1SQ3GXZC75VR","deja-search","deja-vu memory — search the user's past AI coding sessions with the deja CLI. Holds what they already settled and never wrote into the repo (naming rules, banned or already-tried tools, required checks before merge, preferred values, who owns what). Use before your first edit in a task, before you call a change done or ready to merge, before you recommend a tool, library, design or reviewer, before re-debugging an error that may already be solved, when they say 'didn't we fix this before', 'what did we decide about X' or 'I already have that', and before telling them something on this machine does not exist.","https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Fvshulcz\u002Fdeja-vu\u002Fskills\u002Fdeja-search\u002FSKILL.md",[],[121,122,123,124,125,126,127,128,129,39,130,131,132,133,134,135,136,137,138,139],"search","deja search","never","error","ready","memory","re","decide","fix","debugging","when","you","done","reviewer","io","change","cli","merge","past",{"skillNo":141,"name":142,"nameZh":6,"description":143,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":144,"categories":145,"keywords":146,"publishedAt":55},"01M716A3J2W5SENSE9VGMXB375","deja-reflect","End-of-session reflection and memory curation with deja-vu. Review what was decided, what commands broke and what repaired them, and record durable project rules or decisions with deja remember so the next session starts with them.","https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Fvshulcz\u002Fdeja-vu\u002Fskills\u002Fdeja-reflect\u002FSKILL.md",[],[147,148,149,135,150,151,152,153,154,155,156,157,158,159,126,160,161,162,163,164],"deja reflect","reflect","review","with","record","github","next","https","node","Rules","decisions","brew","remember","project rules","project","session","end","reflection",{"skillNo":166,"name":167,"nameZh":6,"description":168,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":169,"categories":170,"keywords":178,"publishedAt":55},"01M715T3RR4BAYSR57HPPTJ0PF","revid","Make, edit, export and post AI videos with Revid (revid.ai) through the Revid MCP server. Use whenever the user wants a short-form or long-form video made (from an idea, a script, a URL, an article, a PDF, a tweet, a product page, their own clips, or a song), wants to find what is going viral on TikTok, YouTube, Instagram or X before making something, wants to edit or re-export an existing Revid project, generate a standalone AI image or clip, make a series episode, or publish and schedule a finished video to connected social accounts. Covers setup (hosted MCP with OAuth, or an API key), the 36 tools, credits, polling and the rules for publishing. Routes to the more specific revid-* skills when one fits.","https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Ftmakersas\u002Frevid-skills\u002Fskills\u002Frevid\u002FSKILL.md",[171,174,175],{"categoryNo":172,"categoryName":173,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000016","图像与多媒体",{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":176,"categoryName":177,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000010","后端与接口",[167,179,180,181,182,183,184,161,185,127,186,187,188,189,131,190,191,192,48,193],"URL","Video","short-form","standalone","PDF","viral","tiktok","short","social","MCP","song","image","mcp server","schedule","publish"]