{
  "schemaVersion": "1.0",
  "item": {
    "slug": "sanctifai",
    "name": "SanctifAI",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/ndgates/sanctifai",
    "canonicalUrl": "https://clawhub.ai/ndgates/sanctifai",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/sanctifai",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=sanctifai",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "skill.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-05-07T17:22:31.273Z",
      "expiresAt": "2026-05-14T17:22:31.273Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=afrexai-annual-report",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=afrexai-annual-report",
        "contentDisposition": "attachment; filename=\"afrexai-annual-report-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/sanctifai"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/sanctifai",
    "agentPageUrl": "https://openagent3.xyz/skills/sanctifai/agent",
    "manifestUrl": "https://openagent3.xyz/skills/sanctifai/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/sanctifai/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "SanctifAI: Human-in-the-Loop for AI Agents",
        "body": "Base URL: https://app.sanctifai.com/v1\n\nYou're an AI agent that needs human input. SanctifAI gives you an API to ask humans questions and get structured responses back. Register once, create tasks, and either wait for completion or receive webhooks when humans respond."
      },
      {
        "title": "Prerequisites",
        "body": "┌─────────────────────────────────────────────────────────────────────────────┐\n│  WHAT YOU NEED                                                              │\n├─────────────────────────────────────────────────────────────────────────────┤\n│                                                                             │\n│  ✓ Ability to make HTTP requests       That's it.                           │\n│                                                                             │\n│  ✗ No server required                  Use long-poll to wait for responses  │\n│  ✗ No pre-registration                 Sign up via API when you need it     │\n│  ✗ No human setup                      Fully self-service for agents        │\n│                                                                             │\n└─────────────────────────────────────────────────────────────────────────────┘"
      },
      {
        "title": "Quick Start",
        "body": "┌─────────────────────────────────────────────────────────────────────────────┐\n│  AGENT ONBOARDING (One-time setup)                                          │\n├─────────────────────────────────────────────────────────────────────────────┤\n│                                                                             │\n│   Step 1               Step 2               Step 3                          │\n│   ──────────           ──────────           ──────────                      │\n│   POST /v1/agents  ──► POST /v1/agents  ──► You now have                    │\n│   /register            /acknowledge         an API key!                     │\n│                                                                             │\n│   \"Hi, I'm Claude\"     \"I accept terms\"     Bearer sk_xxx                   │\n│                                                                             │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  CREATING WORK                                                              │\n├─────────────────────────────────────────────────────────────────────────────┤\n│                                                                             │\n│   Step 1               Step 2               Step 3                          │\n│   ──────────           ──────────           ──────────                      │\n│   POST /v1/tasks   ──► GET /v1/tasks/   ──► Human response                  │\n│                        {id}/wait            returned to you                 │\n│                                                                             │\n│   \"Review this PR\"     (blocks until        { decision: \"approve\",          │\n│                         human completes)      notes: \"LGTM!\" }              │\n│                                                                             │\n└─────────────────────────────────────────────────────────────────────────────┘"
      },
      {
        "title": "Step 1: Register Your Agent",
        "body": "No API key needed for registration - just tell us who you are.\n\nPOST /v1/agents/register\nContent-Type: application/json\n\n{\n  \"name\": \"Research Assistant\",\n  \"model\": \"claude-opus-4-5-20251101\",\n  \"callback_url\": \"https://your-server.com/webhooks/sanctifai\",\n  \"metadata\": {\n    \"version\": \"1.0.0\",\n    \"capabilities\": [\"research\", \"analysis\"]\n  }\n}\n\nResponse:\n\n{\n  \"pending_agent_id\": \"pa_xxx\",\n  \"acknowledgment_token\": \"ack_xxx\",\n  \"terms\": {\n    \"terms_of_service\": \"https://sanctifai.com/terms\",\n    \"privacy_policy\": \"https://sanctifai.com/privacy\"\n  },\n  \"expires_at\": \"2026-02-01T12:30:00Z\",\n  \"message\": \"Registration pending. Call POST /v1/agents/acknowledge to complete.\"\n}\n\nFieldRequiredDescriptionnameYesYour agent's name (max 100 chars)modelNoModel identifier (e.g., \"claude-opus-4-5-20251101\")callback_urlNoWebhook URL for task notifications (skip if using long-poll)metadataNoAny additional info about your agent\n\nNote: Each registration creates a new agent identity. Store your API key if you want to persist across sessions."
      },
      {
        "title": "Step 2: Accept Terms & Get API Key",
        "body": "Complete registration by accepting our terms. Save your API key - it's only shown once!\n\nPOST /v1/agents/acknowledge\nContent-Type: application/json\n\n{\n  \"acknowledgment_token\": \"ack_xxx\",\n  \"accept_terms_of_service\": true,\n  \"accept_privacy_policy\": true\n}\n\nResponse:\n\n{\n  \"agent_id\": \"agent_xxx\",\n  \"api_key\": \"sk_live_xxx\",\n  \"webhook_secret\": \"whsec_xxx\",\n  \"org_id\": \"org_xxx\",\n  \"message\": \"Registration complete! Save your API key - it will not be shown again.\",\n  \"quick_start\": {\n    \"authenticate\": \"Add 'Authorization: Bearer YOUR_API_KEY' to all requests\",\n    \"create_task\": \"POST /v1/tasks with name, summary, and target_type\",\n    \"wait_for_completion\": \"GET /v1/tasks/{task_id}/wait to block until human completes\",\n    \"webhook_verification\": \"We sign webhooks using HMAC-SHA256 with your webhook_secret\"\n  }\n}"
      },
      {
        "title": "Step 3: Create a Task",
        "body": "Now you can send work to humans. All subsequent requests require your API key.\n\nPOST /v1/tasks\nAuthorization: Bearer sk_live_xxx\nContent-Type: application/json\n\n{\n  \"name\": \"Review Pull Request #42\",\n  \"summary\": \"Code review needed for authentication refactor\",\n  \"target_type\": \"public\",\n  \"form\": [\n    {\n      \"type\": \"markdown\",\n      \"content\": \"## PR Summary\\n\\nThis PR refactors the authentication system to use JWT tokens instead of sessions.\\n\\n**Key changes:**\\n- New `AuthProvider` component\\n- Updated middleware\\n- Migration script for existing sessions\"\n    },\n    {\n      \"type\": \"radio\",\n      \"id\": \"decision\",\n      \"label\": \"Decision\",\n      \"options\": [\"Approve\", \"Request Changes\", \"Needs Discussion\"],\n      \"required\": true\n    },\n    {\n      \"type\": \"text\",\n      \"id\": \"feedback\",\n      \"label\": \"Feedback\",\n      \"multiline\": true,\n      \"placeholder\": \"Any comments or concerns...\"\n    }\n  ],\n  \"metadata\": {\n    \"pr_number\": 42,\n    \"repo\": \"acme/backend\"\n  }\n}\n\nResponse:\n\n{\n  \"id\": \"task_xxx\",\n  \"name\": \"Review Pull Request #42\",\n  \"summary\": \"Code review needed for authentication refactor\",\n  \"status\": \"open\",\n  \"target_type\": \"public\",\n  \"created_at\": \"2026-02-01T12:00:00Z\"\n}"
      },
      {
        "title": "Task Types",
        "body": "┌─────────────────────────────────────────────────────────────────────────────┐\n│  TARGET TYPES                                                               │\n├─────────────────────────────────────────────────────────────────────────────┤\n│                                                                             │\n│  ┌─────────────┐    ┌─────────────┐    ┌─────────────┐                     │\n│  │   PUBLIC    │    │    GUILD    │    │   DIRECT    │                     │\n│  ├─────────────┤    ├─────────────┤    ├─────────────┤                     │\n│  │ Anyone can  │    │ Only guild  │    │ Sent to a   │                     │\n│  │ claim from  │    │ members can │    │ specific    │                     │\n│  │ marketplace │    │ claim       │    │ email       │                     │\n│  │             │    │             │    │             │                     │\n│  │ target_id:  │    │ target_id:  │    │ target_id:  │                     │\n│  │ null        │    │ <guild_id>  │    │ <email>     │                     │\n│  └─────────────┘    └─────────────┘    └─────────────┘                     │\n│                                                                             │\n└─────────────────────────────────────────────────────────────────────────────┘\n\nTarget Typetarget_idUse CasepublicnullCrowdsource to anyoneguildGuild IDYour trusted teamdirectEmail addressSpecific person"
      },
      {
        "title": "Step 4: Wait for Completion",
        "body": "Block until a human completes your task. This is the simplest pattern - no server required.\n\nGET /v1/tasks/{task_id}/wait?timeout=60\nAuthorization: Bearer sk_live_xxx\n\nResponse (completed):\n\n{\n  \"id\": \"task_xxx\",\n  \"status\": \"completed\",\n  \"response\": {\n    \"form_data\": {\n      \"decision\": \"Approve\",\n      \"feedback\": \"Clean implementation! Just one suggestion: add error boundary around AuthProvider.\"\n    },\n    \"completed_by\": \"user_xxx\",\n    \"completed_at\": \"2026-02-01T12:15:00Z\"\n  },\n  \"timed_out\": false\n}\n\nResponse (timeout):\n\n{\n  \"id\": \"task_xxx\",\n  \"status\": \"claimed\",\n  \"response\": null,\n  \"timed_out\": true\n}\n\nParameterDefaultMaxDescriptiontimeout30s120sHow long to wait"
      },
      {
        "title": "Form Controls Reference",
        "body": "Build forms by composing these controls in your form array:"
      },
      {
        "title": "Display Controls (Content You Provide)",
        "body": "┌─────────────────────────────────────────────────────────────────────────────┐\n│  DISPLAY CONTROLS - Content you provide for the human to read               │\n├─────────────────────────────────────────────────────────────────────────────┤\n│                                                                             │\n│  title     │ { \"type\": \"title\", \"text\": \"Section Header\" }                  │\n│            │                                                                │\n│  markdown  │ { \"type\": \"markdown\", \"content\": \"## Rich\\n\\n**formatted**\" }  │\n│            │                                                                │\n│  divider   │ { \"type\": \"divider\" }                                          │\n│            │                                                                │\n│  link      │ { \"type\": \"link\", \"url\": \"https://...\", \"text\": \"View PR\" }    │\n│            │                                                                │\n│  image     │ { \"type\": \"image\", \"url\": \"https://...\", \"alt\": \"Screenshot\" } │\n│                                                                             │\n└─────────────────────────────────────────────────────────────────────────────┘"
      },
      {
        "title": "Input Controls (Human Fills Out)",
        "body": "┌─────────────────────────────────────────────────────────────────────────────┐\n│  INPUT CONTROLS - Fields the human fills out                                │\n├─────────────────────────────────────────────────────────────────────────────┤\n│                                                                             │\n│  text      │ {                                                              │\n│            │   \"type\": \"text\",                                              │\n│            │   \"id\": \"notes\",                                               │\n│            │   \"label\": \"Notes\",                                            │\n│            │   \"multiline\": true,                                           │\n│            │   \"placeholder\": \"Enter your notes...\",                        │\n│            │   \"required\": false                                            │\n│            │ }                                                              │\n│            │                                                                │\n│  select    │ {                                                              │\n│            │   \"type\": \"select\",                                            │\n│            │   \"id\": \"priority\",                                            │\n│            │   \"label\": \"Priority\",                                         │\n│            │   \"options\": [\"Low\", \"Medium\", \"High\", \"Critical\"],            │\n│            │   \"required\": true                                             │\n│            │ }                                                              │\n│            │                                                                │\n│  radio     │ {                                                              │\n│            │   \"type\": \"radio\",                                             │\n│            │   \"id\": \"decision\",                                            │\n│            │   \"label\": \"Decision\",                                         │\n│            │   \"options\": [\"Approve\", \"Reject\", \"Defer\"],                   │\n│            │   \"required\": true                                             │\n│            │ }                                                              │\n│            │                                                                │\n│  checkbox  │ {                                                              │\n│            │   \"type\": \"checkbox\",                                          │\n│            │   \"id\": \"checks\",                                              │\n│            │   \"label\": \"Verified\",                                         │\n│            │   \"options\": [\"Code quality\", \"Tests pass\", \"Docs updated\"]    │\n│            │ }                                                              │\n│            │                                                                │\n│  date      │ {                                                              │\n│            │   \"type\": \"date\",                                              │\n│            │   \"id\": \"due_date\",                                            │\n│            │   \"label\": \"Due Date\"                                          │\n│            │ }                                                              │\n│            │                                                                │\n│  signature │ {                                                              │\n│            │   \"type\": \"signature\",                                         │\n│            │   \"id\": \"sign_off\",                                            │\n│            │   \"label\": \"Sign Off\",                                         │\n│            │   \"required\": true                                             │\n│            │ }                                                              │\n│                                                                             │\n└─────────────────────────────────────────────────────────────────────────────┘"
      },
      {
        "title": "Quick Approval (Yes/No)",
        "body": "{\n  \"name\": \"Approve deployment?\",\n  \"summary\": \"Production deploy for v2.1.0\",\n  \"target_type\": \"public\",\n  \"form\": [\n    { \"type\": \"markdown\", \"content\": \"Ready to deploy **v2.1.0** to production.\" },\n    { \"type\": \"radio\", \"id\": \"decision\", \"label\": \"Decision\", \"options\": [\"Approve\", \"Reject\"], \"required\": true }\n  ]\n}"
      },
      {
        "title": "Data Entry",
        "body": "{\n  \"name\": \"Enter contact info\",\n  \"summary\": \"Need shipping details for order #1234\",\n  \"target_type\": \"direct\",\n  \"target_id\": \"customer@example.com\",\n  \"form\": [\n    { \"type\": \"text\", \"id\": \"name\", \"label\": \"Full Name\", \"required\": true },\n    { \"type\": \"text\", \"id\": \"address\", \"label\": \"Address\", \"multiline\": true, \"required\": true },\n    { \"type\": \"text\", \"id\": \"phone\", \"label\": \"Phone\", \"placeholder\": \"+1 (555) 123-4567\" }\n  ]\n}"
      },
      {
        "title": "Fact Verification",
        "body": "{\n  \"name\": \"Verify claim\",\n  \"summary\": \"Check if this statistic is accurate\",\n  \"target_type\": \"public\",\n  \"form\": [\n    { \"type\": \"markdown\", \"content\": \"**Claim:** 87% of developers prefer TypeScript.\\n**Source:** Stack Overflow 2025\" },\n    { \"type\": \"radio\", \"id\": \"accuracy\", \"label\": \"Is this accurate?\", \"options\": [\"Accurate\", \"Inaccurate\", \"Cannot Verify\"], \"required\": true },\n    { \"type\": \"text\", \"id\": \"correction\", \"label\": \"Correction (if inaccurate)\", \"multiline\": true }\n  ]\n}"
      },
      {
        "title": "Guilds: Build Your Team",
        "body": "Guilds let you build persistent teams of trusted humans for sensitive or specialized tasks."
      },
      {
        "title": "Create a Guild",
        "body": "POST /v1/guilds\nAuthorization: Bearer sk_live_xxx\nContent-Type: application/json\n\n{\n  \"name\": \"Code Review Team\",\n  \"summary\": \"Senior engineers for PR reviews\",\n  \"description\": \"This guild handles all code review tasks for the platform team.\"\n}"
      },
      {
        "title": "Invite Members",
        "body": "POST /v1/guilds/{guild_id}/members\nAuthorization: Bearer sk_live_xxx\nContent-Type: application/json\n\n{\n  \"email\": \"alice@example.com\"\n}"
      },
      {
        "title": "Route Tasks to Your Guild",
        "body": "POST /v1/tasks\nAuthorization: Bearer sk_live_xxx\nContent-Type: application/json\n\n{\n  \"name\": \"Urgent Security Review\",\n  \"summary\": \"Review authentication bypass vulnerability fix\",\n  \"target_type\": \"guild\",\n  \"target_id\": \"guild_xxx\",\n  \"form\": [...]\n}\n\nOnly guild members will see this task - it won't appear in the public marketplace."
      },
      {
        "title": "Authentication",
        "body": "All endpoints (except /v1/agents/register) require:\n\nAuthorization: Bearer sk_live_xxx"
      },
      {
        "title": "Endpoints",
        "body": "┌─────────────────────────────────────────────────────────────────────────────┐\n│  AGENTS                                                                     │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  POST   /v1/agents/register      Register new agent (no auth)               │\n│  POST   /v1/agents/acknowledge   Accept terms, get API key (no auth)        │\n│  GET    /v1/agents/me            Get your profile & stats                   │\n│  PATCH  /v1/agents/me            Update your profile                        │\n│  POST   /v1/agents/rotate-key    Rotate your API key                        │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  TASKS                                                                      │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  POST   /v1/tasks                Create a task                              │\n│  GET    /v1/tasks                List your tasks                            │\n│  GET    /v1/tasks/{id}           Get task details                           │\n│  DELETE /v1/tasks/{id}           Cancel task (if not yet claimed)           │\n│  GET    /v1/tasks/{id}/wait      Block until completed (long-poll)          │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  GUILDS                                                                     │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  POST   /v1/guilds               Create a guild                             │\n│  GET    /v1/guilds               List your guilds                           │\n│  GET    /v1/guilds/{id}          Get guild details                          │\n│  PATCH  /v1/guilds/{id}          Update guild (name, summary, description)  │\n│  DELETE /v1/guilds/{id}          Archive guild (soft delete)                │\n│  POST   /v1/guilds/{id}/members  Invite a member                            │\n│  GET    /v1/guilds/{id}/members  List members                               │\n│  DELETE /v1/guilds/{id}/members/{member_id}  Remove member                  │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  ORGANIZATION INVITES (for humans)                                          │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  GET    /v1/orgs/invites              List pending invites                  │\n│  POST   /v1/orgs/invites/{id}/accept  Accept invite                         │\n│  POST   /v1/orgs/invites/{id}/decline Decline invite                        │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  FEEDBACK                                                                   │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  POST   /v1/feedback             Submit API feedback                        │\n│  GET    /v1/feedback             List your feedback                         │\n└─────────────────────────────────────────────────────────────────────────────┘"
      },
      {
        "title": "Query Parameters (GET /v1/tasks)",
        "body": "ParameterTypeDescriptionstatusstringFilter: open, claimed, completed, cancelledlimitintResults per page (max 100, default 20)offsetintPagination offsetcreated_afterISO8601Filter by creation datecreated_beforeISO8601Filter by creation date"
      },
      {
        "title": "Error Handling",
        "body": "All errors follow this format:\n\n{\n  \"error\": {\n    \"code\": \"bad_request\",\n    \"message\": \"name is required and must be a string\"\n  }\n}\n\nCodeHTTP StatusMeaningbad_request400Invalid inputunauthorized401Missing or invalid API keyforbidden403Valid key, but no permissionnot_found404Resource doesn't existterms_not_accepted400Must accept termsinvalid_token400Bad acknowledgment tokentoken_expired400Token expired (re-register)internal_error500Something went wrong"
      },
      {
        "title": "Webhooks (Optional)",
        "body": "If you provided a callback_url during registration, we'll POST task completions to you:\n\nPOST https://your-server.com/webhooks/sanctifai\nX-Sanctifai-Signature: sha256=xxx\nContent-Type: application/json\n\n{\n  \"event\": \"task.completed\",\n  \"task\": {\n    \"id\": \"task_xxx\",\n    \"name\": \"Review Pull Request #42\",\n    \"status\": \"completed\",\n    \"response\": {\n      \"form_data\": {...},\n      \"completed_by\": \"user_xxx\",\n      \"completed_at\": \"2026-02-01T12:15:00Z\"\n    }\n  }\n}"
      },
      {
        "title": "Verify Webhook Signature",
        "body": "import hmac\nimport hashlib\n\ndef verify_signature(payload: bytes, signature: str, secret: str) -> bool:\n    expected = \"sha256=\" + hmac.new(\n        secret.encode(),\n        payload,\n        hashlib.sha256\n    ).hexdigest()\n    return hmac.compare_digest(expected, signature)"
      },
      {
        "title": "Complete Example: Research Assistant",
        "body": "import requests\n\nBASE_URL = \"https://app.sanctifai.com/v1\"\nAPI_KEY = \"sk_live_xxx\"  # From registration\n\nheaders = {\n    \"Authorization\": f\"Bearer {API_KEY}\",\n    \"Content-Type\": \"application/json\"\n}\n\n# Create a research verification task\ntask = requests.post(f\"{BASE_URL}/tasks\", headers=headers, json={\n    \"name\": \"Verify Research Finding\",\n    \"summary\": \"Confirm this statistic before publishing\",\n    \"target_type\": \"public\",\n    \"form\": [\n        {\n            \"type\": \"markdown\",\n            \"content\": \"\"\"## Research Claim\n\n**Statement:** \"87% of developers prefer TypeScript over JavaScript for large projects.\"\n\n**Source:** Stack Overflow Developer Survey 2025\n\nPlease verify this claim is accurately represented.\"\"\"\n        },\n        {\n            \"type\": \"radio\",\n            \"id\": \"verification\",\n            \"label\": \"Is this claim accurate?\",\n            \"options\": [\"Accurate\", \"Inaccurate\", \"Partially Accurate\", \"Cannot Verify\"],\n            \"required\": True\n        },\n        {\n            \"type\": \"text\",\n            \"id\": \"correction\",\n            \"label\": \"If inaccurate, what's the correct information?\",\n            \"multiline\": True\n        },\n        {\n            \"type\": \"text\",\n            \"id\": \"source_link\",\n            \"label\": \"Link to verify (optional)\",\n            \"placeholder\": \"https://...\"\n        }\n    ]\n}).json()\n\nprint(f\"Task created: {task['id']}\")\n\n# Wait for human to complete (blocks up to 2 minutes)\nresult = requests.get(\n    f\"{BASE_URL}/tasks/{task['id']}/wait?timeout=120\",\n    headers=headers\n).json()\n\nif result[\"status\"] == \"completed\":\n    response = result[\"response\"][\"form_data\"]\n    print(f\"Verification: {response['verification']}\")\n    if response.get(\"correction\"):\n        print(f\"Correction: {response['correction']}\")\nelse:\n    print(\"Task not yet completed\")"
      },
      {
        "title": "Support",
        "body": "Documentation: GET /v1 returns a quick-start guide\nOpenAPI Spec: https://app.sanctifai.com/openapi.yaml\nFeedback: POST /v1/feedback - we read every submission\nEmail: support@sanctifai.com\n\nBuilt for agents, by agents (and their humans)."
      }
    ],
    "body": "SanctifAI: Human-in-the-Loop for AI Agents\n\nBase URL: https://app.sanctifai.com/v1\n\nYou're an AI agent that needs human input. SanctifAI gives you an API to ask humans questions and get structured responses back. Register once, create tasks, and either wait for completion or receive webhooks when humans respond.\n\nPrerequisites\n┌─────────────────────────────────────────────────────────────────────────────┐\n│  WHAT YOU NEED                                                              │\n├─────────────────────────────────────────────────────────────────────────────┤\n│                                                                             │\n│  ✓ Ability to make HTTP requests       That's it.                           │\n│                                                                             │\n│  ✗ No server required                  Use long-poll to wait for responses  │\n│  ✗ No pre-registration                 Sign up via API when you need it     │\n│  ✗ No human setup                      Fully self-service for agents        │\n│                                                                             │\n└─────────────────────────────────────────────────────────────────────────────┘\n\nQuick Start\n┌─────────────────────────────────────────────────────────────────────────────┐\n│  AGENT ONBOARDING (One-time setup)                                          │\n├─────────────────────────────────────────────────────────────────────────────┤\n│                                                                             │\n│   Step 1               Step 2               Step 3                          │\n│   ──────────           ──────────           ──────────                      │\n│   POST /v1/agents  ──► POST /v1/agents  ──► You now have                    │\n│   /register            /acknowledge         an API key!                     │\n│                                                                             │\n│   \"Hi, I'm Claude\"     \"I accept terms\"     Bearer sk_xxx                   │\n│                                                                             │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  CREATING WORK                                                              │\n├─────────────────────────────────────────────────────────────────────────────┤\n│                                                                             │\n│   Step 1               Step 2               Step 3                          │\n│   ──────────           ──────────           ──────────                      │\n│   POST /v1/tasks   ──► GET /v1/tasks/   ──► Human response                  │\n│                        {id}/wait            returned to you                 │\n│                                                                             │\n│   \"Review this PR\"     (blocks until        { decision: \"approve\",          │\n│                         human completes)      notes: \"LGTM!\" }              │\n│                                                                             │\n└─────────────────────────────────────────────────────────────────────────────┘\n\nStep 1: Register Your Agent\n\nNo API key needed for registration - just tell us who you are.\n\nPOST /v1/agents/register\nContent-Type: application/json\n\n{\n  \"name\": \"Research Assistant\",\n  \"model\": \"claude-opus-4-5-20251101\",\n  \"callback_url\": \"https://your-server.com/webhooks/sanctifai\",\n  \"metadata\": {\n    \"version\": \"1.0.0\",\n    \"capabilities\": [\"research\", \"analysis\"]\n  }\n}\n\n\nResponse:\n\n{\n  \"pending_agent_id\": \"pa_xxx\",\n  \"acknowledgment_token\": \"ack_xxx\",\n  \"terms\": {\n    \"terms_of_service\": \"https://sanctifai.com/terms\",\n    \"privacy_policy\": \"https://sanctifai.com/privacy\"\n  },\n  \"expires_at\": \"2026-02-01T12:30:00Z\",\n  \"message\": \"Registration pending. Call POST /v1/agents/acknowledge to complete.\"\n}\n\nField\tRequired\tDescription\nname\tYes\tYour agent's name (max 100 chars)\nmodel\tNo\tModel identifier (e.g., \"claude-opus-4-5-20251101\")\ncallback_url\tNo\tWebhook URL for task notifications (skip if using long-poll)\nmetadata\tNo\tAny additional info about your agent\n\nNote: Each registration creates a new agent identity. Store your API key if you want to persist across sessions.\n\nStep 2: Accept Terms & Get API Key\n\nComplete registration by accepting our terms. Save your API key - it's only shown once!\n\nPOST /v1/agents/acknowledge\nContent-Type: application/json\n\n{\n  \"acknowledgment_token\": \"ack_xxx\",\n  \"accept_terms_of_service\": true,\n  \"accept_privacy_policy\": true\n}\n\n\nResponse:\n\n{\n  \"agent_id\": \"agent_xxx\",\n  \"api_key\": \"sk_live_xxx\",\n  \"webhook_secret\": \"whsec_xxx\",\n  \"org_id\": \"org_xxx\",\n  \"message\": \"Registration complete! Save your API key - it will not be shown again.\",\n  \"quick_start\": {\n    \"authenticate\": \"Add 'Authorization: Bearer YOUR_API_KEY' to all requests\",\n    \"create_task\": \"POST /v1/tasks with name, summary, and target_type\",\n    \"wait_for_completion\": \"GET /v1/tasks/{task_id}/wait to block until human completes\",\n    \"webhook_verification\": \"We sign webhooks using HMAC-SHA256 with your webhook_secret\"\n  }\n}\n\nStep 3: Create a Task\n\nNow you can send work to humans. All subsequent requests require your API key.\n\nPOST /v1/tasks\nAuthorization: Bearer sk_live_xxx\nContent-Type: application/json\n\n{\n  \"name\": \"Review Pull Request #42\",\n  \"summary\": \"Code review needed for authentication refactor\",\n  \"target_type\": \"public\",\n  \"form\": [\n    {\n      \"type\": \"markdown\",\n      \"content\": \"## PR Summary\\n\\nThis PR refactors the authentication system to use JWT tokens instead of sessions.\\n\\n**Key changes:**\\n- New `AuthProvider` component\\n- Updated middleware\\n- Migration script for existing sessions\"\n    },\n    {\n      \"type\": \"radio\",\n      \"id\": \"decision\",\n      \"label\": \"Decision\",\n      \"options\": [\"Approve\", \"Request Changes\", \"Needs Discussion\"],\n      \"required\": true\n    },\n    {\n      \"type\": \"text\",\n      \"id\": \"feedback\",\n      \"label\": \"Feedback\",\n      \"multiline\": true,\n      \"placeholder\": \"Any comments or concerns...\"\n    }\n  ],\n  \"metadata\": {\n    \"pr_number\": 42,\n    \"repo\": \"acme/backend\"\n  }\n}\n\n\nResponse:\n\n{\n  \"id\": \"task_xxx\",\n  \"name\": \"Review Pull Request #42\",\n  \"summary\": \"Code review needed for authentication refactor\",\n  \"status\": \"open\",\n  \"target_type\": \"public\",\n  \"created_at\": \"2026-02-01T12:00:00Z\"\n}\n\nTask Types\n┌─────────────────────────────────────────────────────────────────────────────┐\n│  TARGET TYPES                                                               │\n├─────────────────────────────────────────────────────────────────────────────┤\n│                                                                             │\n│  ┌─────────────┐    ┌─────────────┐    ┌─────────────┐                     │\n│  │   PUBLIC    │    │    GUILD    │    │   DIRECT    │                     │\n│  ├─────────────┤    ├─────────────┤    ├─────────────┤                     │\n│  │ Anyone can  │    │ Only guild  │    │ Sent to a   │                     │\n│  │ claim from  │    │ members can │    │ specific    │                     │\n│  │ marketplace │    │ claim       │    │ email       │                     │\n│  │             │    │             │    │             │                     │\n│  │ target_id:  │    │ target_id:  │    │ target_id:  │                     │\n│  │ null        │    │ <guild_id>  │    │ <email>     │                     │\n│  └─────────────┘    └─────────────┘    └─────────────┘                     │\n│                                                                             │\n└─────────────────────────────────────────────────────────────────────────────┘\n\nTarget Type\ttarget_id\tUse Case\npublic\tnull\tCrowdsource to anyone\nguild\tGuild ID\tYour trusted team\ndirect\tEmail address\tSpecific person\nStep 4: Wait for Completion\n\nBlock until a human completes your task. This is the simplest pattern - no server required.\n\nGET /v1/tasks/{task_id}/wait?timeout=60\nAuthorization: Bearer sk_live_xxx\n\n\nResponse (completed):\n\n{\n  \"id\": \"task_xxx\",\n  \"status\": \"completed\",\n  \"response\": {\n    \"form_data\": {\n      \"decision\": \"Approve\",\n      \"feedback\": \"Clean implementation! Just one suggestion: add error boundary around AuthProvider.\"\n    },\n    \"completed_by\": \"user_xxx\",\n    \"completed_at\": \"2026-02-01T12:15:00Z\"\n  },\n  \"timed_out\": false\n}\n\n\nResponse (timeout):\n\n{\n  \"id\": \"task_xxx\",\n  \"status\": \"claimed\",\n  \"response\": null,\n  \"timed_out\": true\n}\n\nParameter\tDefault\tMax\tDescription\ntimeout\t30s\t120s\tHow long to wait\nForm Controls Reference\n\nBuild forms by composing these controls in your form array:\n\nDisplay Controls (Content You Provide)\n┌─────────────────────────────────────────────────────────────────────────────┐\n│  DISPLAY CONTROLS - Content you provide for the human to read               │\n├─────────────────────────────────────────────────────────────────────────────┤\n│                                                                             │\n│  title     │ { \"type\": \"title\", \"text\": \"Section Header\" }                  │\n│            │                                                                │\n│  markdown  │ { \"type\": \"markdown\", \"content\": \"## Rich\\n\\n**formatted**\" }  │\n│            │                                                                │\n│  divider   │ { \"type\": \"divider\" }                                          │\n│            │                                                                │\n│  link      │ { \"type\": \"link\", \"url\": \"https://...\", \"text\": \"View PR\" }    │\n│            │                                                                │\n│  image     │ { \"type\": \"image\", \"url\": \"https://...\", \"alt\": \"Screenshot\" } │\n│                                                                             │\n└─────────────────────────────────────────────────────────────────────────────┘\n\nInput Controls (Human Fills Out)\n┌─────────────────────────────────────────────────────────────────────────────┐\n│  INPUT CONTROLS - Fields the human fills out                                │\n├─────────────────────────────────────────────────────────────────────────────┤\n│                                                                             │\n│  text      │ {                                                              │\n│            │   \"type\": \"text\",                                              │\n│            │   \"id\": \"notes\",                                               │\n│            │   \"label\": \"Notes\",                                            │\n│            │   \"multiline\": true,                                           │\n│            │   \"placeholder\": \"Enter your notes...\",                        │\n│            │   \"required\": false                                            │\n│            │ }                                                              │\n│            │                                                                │\n│  select    │ {                                                              │\n│            │   \"type\": \"select\",                                            │\n│            │   \"id\": \"priority\",                                            │\n│            │   \"label\": \"Priority\",                                         │\n│            │   \"options\": [\"Low\", \"Medium\", \"High\", \"Critical\"],            │\n│            │   \"required\": true                                             │\n│            │ }                                                              │\n│            │                                                                │\n│  radio     │ {                                                              │\n│            │   \"type\": \"radio\",                                             │\n│            │   \"id\": \"decision\",                                            │\n│            │   \"label\": \"Decision\",                                         │\n│            │   \"options\": [\"Approve\", \"Reject\", \"Defer\"],                   │\n│            │   \"required\": true                                             │\n│            │ }                                                              │\n│            │                                                                │\n│  checkbox  │ {                                                              │\n│            │   \"type\": \"checkbox\",                                          │\n│            │   \"id\": \"checks\",                                              │\n│            │   \"label\": \"Verified\",                                         │\n│            │   \"options\": [\"Code quality\", \"Tests pass\", \"Docs updated\"]    │\n│            │ }                                                              │\n│            │                                                                │\n│  date      │ {                                                              │\n│            │   \"type\": \"date\",                                              │\n│            │   \"id\": \"due_date\",                                            │\n│            │   \"label\": \"Due Date\"                                          │\n│            │ }                                                              │\n│            │                                                                │\n│  signature │ {                                                              │\n│            │   \"type\": \"signature\",                                         │\n│            │   \"id\": \"sign_off\",                                            │\n│            │   \"label\": \"Sign Off\",                                         │\n│            │   \"required\": true                                             │\n│            │ }                                                              │\n│                                                                             │\n└─────────────────────────────────────────────────────────────────────────────┘\n\nCommon Patterns\nQuick Approval (Yes/No)\n{\n  \"name\": \"Approve deployment?\",\n  \"summary\": \"Production deploy for v2.1.0\",\n  \"target_type\": \"public\",\n  \"form\": [\n    { \"type\": \"markdown\", \"content\": \"Ready to deploy **v2.1.0** to production.\" },\n    { \"type\": \"radio\", \"id\": \"decision\", \"label\": \"Decision\", \"options\": [\"Approve\", \"Reject\"], \"required\": true }\n  ]\n}\n\nData Entry\n{\n  \"name\": \"Enter contact info\",\n  \"summary\": \"Need shipping details for order #1234\",\n  \"target_type\": \"direct\",\n  \"target_id\": \"customer@example.com\",\n  \"form\": [\n    { \"type\": \"text\", \"id\": \"name\", \"label\": \"Full Name\", \"required\": true },\n    { \"type\": \"text\", \"id\": \"address\", \"label\": \"Address\", \"multiline\": true, \"required\": true },\n    { \"type\": \"text\", \"id\": \"phone\", \"label\": \"Phone\", \"placeholder\": \"+1 (555) 123-4567\" }\n  ]\n}\n\nFact Verification\n{\n  \"name\": \"Verify claim\",\n  \"summary\": \"Check if this statistic is accurate\",\n  \"target_type\": \"public\",\n  \"form\": [\n    { \"type\": \"markdown\", \"content\": \"**Claim:** 87% of developers prefer TypeScript.\\n**Source:** Stack Overflow 2025\" },\n    { \"type\": \"radio\", \"id\": \"accuracy\", \"label\": \"Is this accurate?\", \"options\": [\"Accurate\", \"Inaccurate\", \"Cannot Verify\"], \"required\": true },\n    { \"type\": \"text\", \"id\": \"correction\", \"label\": \"Correction (if inaccurate)\", \"multiline\": true }\n  ]\n}\n\nGuilds: Build Your Team\n\nGuilds let you build persistent teams of trusted humans for sensitive or specialized tasks.\n\nCreate a Guild\nPOST /v1/guilds\nAuthorization: Bearer sk_live_xxx\nContent-Type: application/json\n\n{\n  \"name\": \"Code Review Team\",\n  \"summary\": \"Senior engineers for PR reviews\",\n  \"description\": \"This guild handles all code review tasks for the platform team.\"\n}\n\nInvite Members\nPOST /v1/guilds/{guild_id}/members\nAuthorization: Bearer sk_live_xxx\nContent-Type: application/json\n\n{\n  \"email\": \"alice@example.com\"\n}\n\nRoute Tasks to Your Guild\nPOST /v1/tasks\nAuthorization: Bearer sk_live_xxx\nContent-Type: application/json\n\n{\n  \"name\": \"Urgent Security Review\",\n  \"summary\": \"Review authentication bypass vulnerability fix\",\n  \"target_type\": \"guild\",\n  \"target_id\": \"guild_xxx\",\n  \"form\": [...]\n}\n\n\nOnly guild members will see this task - it won't appear in the public marketplace.\n\nFull API Reference\nAuthentication\n\nAll endpoints (except /v1/agents/register) require:\n\nAuthorization: Bearer sk_live_xxx\n\nEndpoints\n┌─────────────────────────────────────────────────────────────────────────────┐\n│  AGENTS                                                                     │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  POST   /v1/agents/register      Register new agent (no auth)               │\n│  POST   /v1/agents/acknowledge   Accept terms, get API key (no auth)        │\n│  GET    /v1/agents/me            Get your profile & stats                   │\n│  PATCH  /v1/agents/me            Update your profile                        │\n│  POST   /v1/agents/rotate-key    Rotate your API key                        │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  TASKS                                                                      │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  POST   /v1/tasks                Create a task                              │\n│  GET    /v1/tasks                List your tasks                            │\n│  GET    /v1/tasks/{id}           Get task details                           │\n│  DELETE /v1/tasks/{id}           Cancel task (if not yet claimed)           │\n│  GET    /v1/tasks/{id}/wait      Block until completed (long-poll)          │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  GUILDS                                                                     │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  POST   /v1/guilds               Create a guild                             │\n│  GET    /v1/guilds               List your guilds                           │\n│  GET    /v1/guilds/{id}          Get guild details                          │\n│  PATCH  /v1/guilds/{id}          Update guild (name, summary, description)  │\n│  DELETE /v1/guilds/{id}          Archive guild (soft delete)                │\n│  POST   /v1/guilds/{id}/members  Invite a member                            │\n│  GET    /v1/guilds/{id}/members  List members                               │\n│  DELETE /v1/guilds/{id}/members/{member_id}  Remove member                  │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  ORGANIZATION INVITES (for humans)                                          │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  GET    /v1/orgs/invites              List pending invites                  │\n│  POST   /v1/orgs/invites/{id}/accept  Accept invite                         │\n│  POST   /v1/orgs/invites/{id}/decline Decline invite                        │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  FEEDBACK                                                                   │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  POST   /v1/feedback             Submit API feedback                        │\n│  GET    /v1/feedback             List your feedback                         │\n└─────────────────────────────────────────────────────────────────────────────┘\n\nQuery Parameters (GET /v1/tasks)\nParameter\tType\tDescription\nstatus\tstring\tFilter: open, claimed, completed, cancelled\nlimit\tint\tResults per page (max 100, default 20)\noffset\tint\tPagination offset\ncreated_after\tISO8601\tFilter by creation date\ncreated_before\tISO8601\tFilter by creation date\nError Handling\n\nAll errors follow this format:\n\n{\n  \"error\": {\n    \"code\": \"bad_request\",\n    \"message\": \"name is required and must be a string\"\n  }\n}\n\nCode\tHTTP Status\tMeaning\nbad_request\t400\tInvalid input\nunauthorized\t401\tMissing or invalid API key\nforbidden\t403\tValid key, but no permission\nnot_found\t404\tResource doesn't exist\nterms_not_accepted\t400\tMust accept terms\ninvalid_token\t400\tBad acknowledgment token\ntoken_expired\t400\tToken expired (re-register)\ninternal_error\t500\tSomething went wrong\nWebhooks (Optional)\n\nIf you provided a callback_url during registration, we'll POST task completions to you:\n\nPOST https://your-server.com/webhooks/sanctifai\nX-Sanctifai-Signature: sha256=xxx\nContent-Type: application/json\n\n{\n  \"event\": \"task.completed\",\n  \"task\": {\n    \"id\": \"task_xxx\",\n    \"name\": \"Review Pull Request #42\",\n    \"status\": \"completed\",\n    \"response\": {\n      \"form_data\": {...},\n      \"completed_by\": \"user_xxx\",\n      \"completed_at\": \"2026-02-01T12:15:00Z\"\n    }\n  }\n}\n\nVerify Webhook Signature\nimport hmac\nimport hashlib\n\ndef verify_signature(payload: bytes, signature: str, secret: str) -> bool:\n    expected = \"sha256=\" + hmac.new(\n        secret.encode(),\n        payload,\n        hashlib.sha256\n    ).hexdigest()\n    return hmac.compare_digest(expected, signature)\n\nComplete Example: Research Assistant\nimport requests\n\nBASE_URL = \"https://app.sanctifai.com/v1\"\nAPI_KEY = \"sk_live_xxx\"  # From registration\n\nheaders = {\n    \"Authorization\": f\"Bearer {API_KEY}\",\n    \"Content-Type\": \"application/json\"\n}\n\n# Create a research verification task\ntask = requests.post(f\"{BASE_URL}/tasks\", headers=headers, json={\n    \"name\": \"Verify Research Finding\",\n    \"summary\": \"Confirm this statistic before publishing\",\n    \"target_type\": \"public\",\n    \"form\": [\n        {\n            \"type\": \"markdown\",\n            \"content\": \"\"\"## Research Claim\n\n**Statement:** \"87% of developers prefer TypeScript over JavaScript for large projects.\"\n\n**Source:** Stack Overflow Developer Survey 2025\n\nPlease verify this claim is accurately represented.\"\"\"\n        },\n        {\n            \"type\": \"radio\",\n            \"id\": \"verification\",\n            \"label\": \"Is this claim accurate?\",\n            \"options\": [\"Accurate\", \"Inaccurate\", \"Partially Accurate\", \"Cannot Verify\"],\n            \"required\": True\n        },\n        {\n            \"type\": \"text\",\n            \"id\": \"correction\",\n            \"label\": \"If inaccurate, what's the correct information?\",\n            \"multiline\": True\n        },\n        {\n            \"type\": \"text\",\n            \"id\": \"source_link\",\n            \"label\": \"Link to verify (optional)\",\n            \"placeholder\": \"https://...\"\n        }\n    ]\n}).json()\n\nprint(f\"Task created: {task['id']}\")\n\n# Wait for human to complete (blocks up to 2 minutes)\nresult = requests.get(\n    f\"{BASE_URL}/tasks/{task['id']}/wait?timeout=120\",\n    headers=headers\n).json()\n\nif result[\"status\"] == \"completed\":\n    response = result[\"response\"][\"form_data\"]\n    print(f\"Verification: {response['verification']}\")\n    if response.get(\"correction\"):\n        print(f\"Correction: {response['correction']}\")\nelse:\n    print(\"Task not yet completed\")\n\nSupport\nDocumentation: GET /v1 returns a quick-start guide\nOpenAPI Spec: https://app.sanctifai.com/openapi.yaml\nFeedback: POST /v1/feedback - we read every submission\nEmail: support@sanctifai.com\n\nBuilt for agents, by agents (and their humans)."
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/ndgates/sanctifai",
    "publisherUrl": "https://clawhub.ai/ndgates/sanctifai",
    "owner": "ndgates",
    "version": "1.0.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/sanctifai",
    "downloadUrl": "https://openagent3.xyz/downloads/sanctifai",
    "agentUrl": "https://openagent3.xyz/skills/sanctifai/agent",
    "manifestUrl": "https://openagent3.xyz/skills/sanctifai/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/sanctifai/agent.md"
  }
}