{
 "slug": "twenty",
 "name": "Twenty",
 "url": "https://twenty.com",
 "domain": "twenty.com",
 "category": "crm",
 "category_name": "CRM",
 "tested_at": "2026-10-02",
 "run": "20261002T143441Z",
 "draft": false,
 "reviewed": true,
 "owner_verified": null,
 "origin": "editorial",
 "history": [
  {
   "run": "20261001T214935Z",
   "date": "2026-10-01",
   "level": 4,
   "engine": {
    "runner": "omp",
    "model": null,
    "driver": null,
    "signed": true,
    "inbox": [
     "agentdrives.com"
    ],
    "robots": "start"
   }
  },
  {
   "run": "20261002T143441Z",
   "date": "2026-10-02",
   "level": 4,
   "engine": {
    "runner": "omp",
    "model": "claude-opus-5-5",
    "driver": 2,
    "signed": true,
    "inbox": [
     "agentdrives.com"
    ],
    "robots": "start"
   }
  }
 ],
 "level": 4,
 "level_name": "Runs on its own",
 "level_selfhost": null,
 "entry": "self-start",
 "door": {
  "passed": 2,
  "tries": 2,
  "self_start": true
 },
 "badges": [
  "agent-can-leave"
 ],
 "stages": [
  {
   "key": "in",
   "label": "Access",
   "state": "yes",
   "text": "Gets in on its own: sign-up in a browser"
  },
  {
   "key": "work",
   "label": "Use",
   "state": "yes",
   "text": "Work done: 80% of the core"
  },
  {
   "key": "pay",
   "label": "Pay",
   "state": "unreached",
   "text": "Payment not reached",
   "value": "unreached",
   "route": "card_checkout"
  },
  {
   "key": "leave",
   "label": "Leave",
   "state": "yes",
   "text": "Leaves on its own: cancels on its own, deletes its account",
   "left": "deleted"
  }
 ],
 "outcomes": [
  {
   "key": "find",
   "label": "Find",
   "state": "yes",
   "text": "Docs agents can read: llms.txt, an OpenAPI and an MCP server",
   "have": [
    "llms_txt",
    "openapi",
    "mcp"
   ]
  },
  {
   "key": "access",
   "label": "Access",
   "state": "yes",
   "text": "Gets in on its own: sign-up in a browser",
   "stage": "in"
  },
  {
   "key": "use",
   "label": "Use",
   "state": "yes",
   "text": "Work done: 80% of the core",
   "stage": "work"
  },
  {
   "key": "pay",
   "label": "Pay",
   "state": "unreached",
   "text": "Payment not reached",
   "value": "unreached",
   "route": "card_checkout",
   "stage": "pay"
  },
  {
   "key": "leave",
   "label": "Leave",
   "state": "yes",
   "text": "Leaves on its own: cancels on its own, deletes its account",
   "left": "deleted",
   "stage": "leave"
  }
 ],
 "access": [
  {
   "key": "browser_signup",
   "label": "Sign-up in a browser",
   "routes": [],
   "minutes": 10.3,
   "core": "8/10"
  }
 ],
 "minutes": 10.3,
 "next": {
  "to": 5,
  "text": "Next: pay without a person"
 },
 "stop": null,
 "core": "8/10",
 "scores": {
  "coverage": 65,
  "reliability": 88,
  "resilience": null,
  "setup": 100,
  "surface_coverage": null,
  "docs_accuracy": null,
  "docs_completeness": null
 },
 "parts": {
  "holds_up": null,
  "docs_match": null,
  "setup": 100,
  "security": null,
  "standards": []
 },
 "reliability_method": "first-try",
 "resilience": null,
 "stress": [],
 "surface_audit": null,
 "coverage_core": 80,
 "after_wall": null,
 "coverage_source": "computed",
 "driver": {
  "version": 2,
  "model": "claude-opus-5-5",
  "profile": "full",
  "assisted": false,
  "handoff": null,
  "prompt_sha": null,
  "kb_version": null,
  "identity": null
 },
 "methodology": 15,
 "rules_date": "2026-10-15",
 "engine": {
  "runner": "omp",
  "model": "claude-opus-5-5",
  "driver": 2,
  "signed": true,
  "inbox": [
   "agentdrives.com"
  ],
  "robots": "start"
 },
 "same_level_drives": 2,
 "drives": 2,
 "works_assisted": null,
 "freshness": "fresh",
 "nothing_to_pay": false,
 "core_gated": false,
 "profiles": {},
 "agent_check": null,
 "agent_pass": {
  "rung": "signup",
  "vendor": "reCAPTCHA (invisible)",
  "signed": true
 },
 "who_gets_in": {
  "server": {
   "state": "in"
  },
  "signed": {
   "state": "page",
   "kind": "home",
   "at": "2026-10-13"
  },
  "browser": {
   "state": "in",
   "measured": false
  },
  "our_key": "pending",
  "robots": null,
  "tip": false
 },
 "ladder": {
  "docs": {
   "status": "headless",
   "note": "twenty.com/llms.txt and docs.twenty.com/llms.txt (plain text), MCP server card at /.well-known/mcp/server-card.json, RFC 9727 API catalog at /.well-known/api-catalog. llms.txt explicitly allows agent-driven sign-up (ToS section 10)."
  },
  "signup": {
   "status": "browser",
   "note": "Email + password on app.twenty.com in our agent's browser. Invisible reCAPTCHA let our signed agent through, no visible challenge. There is no headless sign-up API; llms.txt says this is deliberate. Onboarding (workspace name/subdomain, skip mailbox sync, apps, invites, choose plan) is browser only."
  },
  "verify": {
   "status": "browser",
   "note": "The verification mail arrived within a minute. Opening the link showed 'Email Verification Failed: You must be authenticated' anyway, but signing in afterwards went straight on to workspace creation, so the address had been accepted."
  },
  "credentials": {
   "status": "browser",
   "note": "API key created under Settings > MCP & APIs > API (Admin role, never expires). It is shown once; to capture it we had to regenerate it. OAuth 2.1 with dynamic client registration also works headless, apart from one consent click in a logged-in browser.",
   "via": ""
  },
  "first_call": {
   "status": "headless",
   "note": "GET /rest/companies with Bearer key -> 200; per-workspace OpenAPI (322 core + 27 metadata paths); MCP initialize + tools/list over streamable HTTP."
  },
  "first_action": {
   "status": "headless",
   "note": "Created a company through MCP execute_tool create_one_company and read it back through REST."
  },
  "pay": {
   "status": "",
   "grade": "P1",
   "rails": [],
   "first_party": false,
   "rail_scope": "none",
   "trial_path": "no-card trial",
   "note": "No agent payment rail: x402./mpp./agents. subdomains 404, no 402 anywhere, no /.well-known/ucp, no billing API in docs. A 7-day Pro trial starts without a card (a 30-day trial needs billing details). The only purchase path is in the web app: Settings > Billing > Subscribe Now > 'Add credit card'. Clicking that in our agent's browser did nothing: no page change, no popup, no Stripe request (an hCaptcha script was on the page). So a person has to add the card.",
   "reached": false
  },
  "cancel": {
   "status": "browser",
   "grade": "X3",
   "note": "'Cancel Plan' button under Settings > Billing; deleting the workspace also ended the trial. No billing API. Nothing recurring was ever started (no card)."
  },
  "delete": {
   "status": "browser",
   "note": "Settings > General > Delete workspace, type your email to confirm. Afterwards the API returned 401 WORKSPACE_NOT_FOUND. No documented API route for deleting the workspace or account.",
   "left": "deleted",
   "account": true
  }
 },
 "routes": [],
 "checkout": null,
 "docs": null,
 "claims": null,
 "pay_options": {
  "checked": "2026-10-02",
  "source": "drive",
  "options": [],
  "agentic": [],
  "paid": null,
  "exercised": null,
  "detected_grade": null,
  "trial": {
   "no_card": true,
   "card_required": null,
   "free_plan": null
  },
  "owner_fixes": [
   {
    "title": "Accept x402 or MPP on your API",
    "how": "Answer an unpaid call with 402 and a payment challenge, so an agent pays per call or buys credits without an account or a card."
   },
   {
    "title": "List your plans on Stripe Projects",
    "how": "Agents buy a plan with `stripe projects add`, paid with a token under a spend cap the owner sets (projects.dev)."
   }
  ]
 },
 "surfaces": {
  "api": true,
  "openapi": true,
  "cli": true,
  "sdk": false,
  "mcp": "official",
  "llms_txt": true,
  "webhooks": true,
  "sandbox": false
 },
 "surface_notes": {
  "api": "REST + GraphQL per workspace, plus metadata API; one Bearer key covers all of them. Pro plan: 50 API calls per minute (from the pricing page)",
  "openapi": "Generated per workspace: 322 core paths, 27 metadata paths, includes custom objects",
  "mcp": "Official, at https://{workspace}/mcp. 7 meta-tools (learn_tools/execute_tool/get_tool_catalog/load_skills…) give access to 324 catalog tools: CRUD, views, workflows, dashboards, roles, webhooks, metadata. Accepts an API key or OAuth 2.1 with DCR",
  "cli": "App-development CLI exists according to docs; not tested",
  "webhooks": "Registered through MCP and listed in REST with a signing secret; delivery not verified"
 },
 "can_do": [
  "Create, update, relate and delete companies, people, opportunities, notes and tasks through MCP or REST",
  "Define a custom object with number and relation fields and use it right away over REST and GraphQL",
  "Build a saved kanban view with a filter and a sort through MCP",
  "Build, activate and trigger a two-step workflow and read its run log",
  "Put an AI agent step into a workflow and get its answer written back as a note",
  "Build a dashboard with a count chart through MCP",
  "Register an OAuth client (dynamic registration) and call the API with the token after one consent click",
  "Batch-create records in one REST call"
 ],
 "cannot_do": [
  {
   "what": "Sign up, verify and create a workspace without a browser",
   "why": "Sign-up is web-only and protected by reCAPTCHA, by design according to llms.txt"
  },
  {
   "what": "Mint the first API key headless",
   "why": "The key is created in Settings in the web app; the OAuth route needs a consent click in a logged-in browser"
  },
  {
   "what": "Buy a plan",
   "why": "No billing API or agent payment rail; 'Add credit card' in the web app opened nothing in our agent's browser"
  },
  {
   "what": "Delete the workspace or account through the API",
   "why": "Only Settings > General > Delete workspace in the web app"
  },
  {
   "what": "Connect a mailbox and calendar",
   "why": "Google or Microsoft OAuth only; we had no such account"
  }
 ],
 "blockers": [
  "Sign-up, workspace onboarding and the first API key are web-only",
  "Purchase only through 'Add credit card' in the web app, which did nothing in our agent's browser"
 ],
 "tips_for_owner": [
  "Let an MCP OAuth login create the workspace",
  "Fix trigger variable syntax in workflow tool docs",
  "Make workflow step creation atomic and validated",
  "Offer a billing link or API for agents",
  "Fix the misleading email verification error page",
  "Add an API route to delete a workspace"
 ],
 "tips_for_agents": [
  "Use the MCP server at https://{workspace}.twenty.com/mcp with 'Authorization: Bearer <api key>'. tools/list only shows 7 meta-tools: call get_tool_catalog once, then learn_tools for schemas and execute_tool to run.",
  "MCP find_many_* needs an explicit select parameter.",
  "Workflow step ids must be UUIDs. In database-event triggers, read fields as {{trigger.properties.after.<field>}}, not {{trigger.object.<field>}}.",
  "AI_AGENT steps: create_workflow_version_step, then update_agent, then update_workflow_version_step. Active versions are read-only, so use create_draft_from_workflow_version.",
  "After create_workflow_version_step, check the step's settings: CREATE_RECORD defaulted to company, which can loop on a company.created trigger.",
  "company.domainName is unique per workspace; a duplicate returns 400 with a constraint name.",
  "The API key is shown once; copy it at creation or you will have to regenerate it."
 ],
 "selfhost": null,
 "summary": "Once a workspace exists, Twenty is one of the most agent-ready CRMs: its official MCP server (324 tools) and REST/GraphQL let an agent run records, custom objects, views, workflows, AI-agent steps and dashboards end to end. Sign-up, onboarding and the first API key need a browser, but invisible reCAPTCHA let our agent through and a 7-day trial needs no card. Paying is web-only, and the card step did not open for our agent's browser.",
 "wall": "Purchase: card form never opened",
 "plan_scope": "no-card trial (Pro plan, 7 days)",
 "robots_stop": null,
 "robots": null,
 "plain": {
  "summary": "Twenty is a CRM that agents can run almost entirely through official APIs and an AI assistant protocol (MCP) once an account exists. Creating that account, getting the first developer key, and paying both require a real web browser, and in this test the sign-up step was not seriously blocked, but the final payment step never opened the card form for the automated browser.",
  "can_do": [
   "Create, update, link and delete contacts, companies and deals",
   "Add new custom record types and fields and use them right away",
   "Build filtered views like kanban boards",
   "Build and run multi-step automations, including one that calls an AI model",
   "Build a chart dashboard",
   "Log in on behalf of a user without a password using a secure login flow"
  ],
  "cannot_do": [
   {
    "what": "Sign up, verify the email and create the workspace without opening a browser",
    "why": "Sign-up only exists as a web form; the company intentionally keeps it browser-only"
   },
   {
    "what": "Get the first developer key without a browser",
    "why": "The key is only shown once inside the web settings page"
   },
   {
    "what": "Buy a paid plan",
    "why": "Clicking 'Add credit card' did nothing in the automated browser and there is no other way to pay"
   },
   {
    "what": "Remove the workspace via an API call",
    "why": "Deletion is a web-only settings action"
   },
   {
    "what": "Sync a Google or Microsoft inbox",
    "why": "The tester had no such email account to connect, not a product limit"
   }
  ]
 },
 "plan_gated": [
  {
   "capability": "Row-level permissions",
   "plan": "Organization ($19/user/month)",
   "evidence": "twenty.com/pricing comparison: Row-level permissions No on Pro"
  },
  {
   "capability": "Audit logs",
   "plan": "Organization",
   "evidence": "pricing comparison: Audit logs No on Pro"
  },
  {
   "capability": "SAML/OIDC SSO",
   "plan": "Organization",
   "evidence": "pricing comparison: SSO No on Pro"
  },
  {
   "capability": "Custom domain",
   "plan": "Organization",
   "evidence": "pricing comparison: Custom domain No on Pro"
  },
  {
   "capability": "SCIM",
   "plan": "Enterprise (from $50k/year)",
   "evidence": "pricing comparison: SCIM provisioning Enterprise only"
  },
  {
   "capability": "IP allow-listing",
   "plan": "Enterprise",
   "evidence": "pricing comparison: IP allow-listing Enterprise only"
  }
 ],
 "reply": null,
 "capabilities": [
  {
   "id": "cap-01",
   "group": "Records",
   "capability": "Create/update/delete a CRM record (person, company, opportunity, custom object)",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST/PATCH/DELETE /rest/{objects}",
    "mcp": "create_one_{object} / update_one_{object} / delete_one_{object}",
    "cli": null,
    "ui": "Object table view → New Record"
   },
   "check": "GET /rest/{objects}/{id} returns the created/updated fields or 404 after delete",
   "source": "https://docs.twenty.com/getting-started/core-concepts/data-model.md; https://docs.twenty.com/developers/extend/api.md"
  },
  {
   "id": "cap-02",
   "group": "Records",
   "capability": "Define a custom object and custom fields for the data model",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /rest/metadata/objects, /rest/metadata/fields",
    "mcp": null,
    "cli": null,
    "ui": "Settings → Data Model → + Object/Field"
   },
   "check": "GET /rest/metadata/objects lists the new object/field; new object immediately gets REST/GraphQL endpoints",
   "source": "https://docs.twenty.com/user-guide/data-model/overview.md; https://docs.twenty.com/developers/extend/api.md"
  },
  {
   "id": "cap-03",
   "group": "Records",
   "capability": "Relate records across objects (relation fields)",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "PATCH /rest/{objects}/{id} with relation field",
    "mcp": "update_one_{object}",
    "cli": null,
    "ui": "Record detail panel → relation field"
   },
   "check": "GET on either record shows the linked record in the relation field",
   "source": "https://docs.twenty.com/getting-started/core-concepts/data-model.md"
  },
  {
   "id": "cap-04",
   "group": "Views & Pipelines",
   "capability": "Build and save a filtered/sorted/grouped view (table, kanban, calendar)",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /rest/metadata/viewSettings (via views)",
    "mcp": null,
    "cli": null,
    "ui": "Object view → Filter/Sort/Options → Save view"
   },
   "check": "Reloading the object tab shows the saved view with its filters/columns applied",
   "source": "https://docs.twenty.com/getting-started/key-features.md"
  },
  {
   "id": "cap-05",
   "group": "Workflows",
   "capability": "Build a no-code workflow (trigger → multi-step actions)",
   "weight": "core",
   "plan": "paid",
   "surfaces": {
    "api": "REST/GraphQL on Workflow metadata objects",
    "mcp": null,
    "cli": null,
    "ui": "Workflows → New Workflow → builder"
   },
   "check": "Workflow run history shows an execution with each step's output",
   "source": "https://docs.twenty.com/getting-started/core-concepts/workflows.md; https://twenty.com/pricing"
  },
  {
   "id": "cap-06",
   "group": "Workflows",
   "capability": "Trigger a workflow (record event, manual button, schedule, or incoming webhook)",
   "weight": "core",
   "plan": "paid",
   "surfaces": {
    "api": "POST webhook URL for webhook trigger",
    "mcp": null,
    "cli": null,
    "ui": "Workflow trigger config; manual trigger button on record"
   },
   "check": "A new workflow run appears in the run log timed to the trigger event",
   "source": "https://docs.twenty.com/getting-started/core-concepts/workflows.md"
  },
  {
   "id": "cap-07",
   "group": "Workflows",
   "capability": "Chain actions in a workflow: record ops, send email, HTTP request, run code, branch, iterate, delay, collect form input, invoke AI agent",
   "weight": "core",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Workflow step editor → Add step"
   },
   "check": "Workflow run detail shows each configured step executed in order with its result",
   "source": "https://docs.twenty.com/getting-started/core-concepts/workflows.md"
  },
  {
   "id": "cap-08",
   "group": "AI",
   "capability": "Ask the AI chatbot questions about CRM data in natural language",
   "weight": "core",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "AI chatbot panel"
   },
   "check": "Chatbot reply cites/reflects actual record data matching a manual filter query",
   "source": "https://docs.twenty.com/getting-started/core-concepts/ai.md"
  },
  {
   "id": "cap-09",
   "group": "AI",
   "capability": "Configure an AI agent with custom skills to run autonomous multi-step tasks (enrich records, draft/send emails, analyze pipeline)",
   "weight": "core",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Settings → AI Agents; Workflow step 'AI Agent'"
   },
   "check": "Agent's target record is updated/emailed with the expected field or message after a run",
   "source": "https://docs.twenty.com/getting-started/core-concepts/ai.md; https://twenty.com/pricing"
  },
  {
   "id": "cap-10",
   "group": "Email & Calendar",
   "capability": "Connect a Google Workspace or Microsoft 365 account to sync email and calendar to records",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Settings → Accounts → Connect account"
   },
   "check": "Person/Company record's Emails/Events tab shows synced messages and meetings from the connected mailbox",
   "source": "https://docs.twenty.com/getting-started/core-concepts/calendar-and-email.md; https://docs.twenty.com/getting-started/key-features.md"
  },
  {
   "id": "cap-11",
   "group": "Dashboards",
   "capability": "Build a custom dashboard with configurable chart/report widgets",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Dashboards → New Dashboard → Add widget"
   },
   "check": "Dashboard renders a chart whose numbers match a manual count/filter on the underlying object",
   "source": "https://docs.twenty.com/getting-started/core-concepts/dashboards.md; https://twenty.com/pricing"
  },
  {
   "id": "cap-12",
   "group": "Data Migration",
   "capability": "Import records in bulk via CSV/XLSX upload with field mapping and error review",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Object view → ⋮ Command Menu → Import records"
   },
   "check": "Object table row count increases by the number of valid rows in the uploaded file",
   "source": "https://docs.twenty.com/user-guide/data-migration/overview.md"
  },
  {
   "id": "cap-13",
   "group": "Data Migration",
   "capability": "Export a view's visible data to CSV",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Object view → ⋮ → Export view"
   },
   "check": "Downloaded CSV contains exactly the columns/rows visible in the current view (max 20,000 records)",
   "source": "https://docs.twenty.com/user-guide/data-migration/overview.md"
  },
  {
   "id": "cap-14",
   "group": "Data Migration",
   "capability": "Bulk import/export records programmatically via the API for large datasets",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /rest/{objects} batch (up to 60/request)",
    "mcp": null,
    "cli": null,
    "ui": null
   },
   "check": "Batch POST response returns created ids for all submitted records, confirmed by follow-up GET",
   "source": "https://docs.twenty.com/developers/extend/api.md; https://docs.twenty.com/user-guide/data-migration/overview.md"
  },
  {
   "id": "cap-15",
   "group": "Notes & Tasks",
   "capability": "Attach notes to a record",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /rest/notes",
    "mcp": "create_one_note",
    "cli": null,
    "ui": "Record detail → Notes tab"
   },
   "check": "GET /rest/notes?filter shows the note linked to the target record id",
   "source": "https://docs.twenty.com/getting-started/core-concepts/data-model.md"
  },
  {
   "id": "cap-16",
   "group": "Notes & Tasks",
   "capability": "Create and assign tasks linked to records",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /rest/tasks",
    "mcp": "create_one_task",
    "cli": null,
    "ui": "Record detail → Tasks tab / Tasks object"
   },
   "check": "Task record shows assignee and linked record; status updates on completion",
   "source": "https://docs.twenty.com/getting-started/core-concepts/data-model.md"
  },
  {
   "id": "cap-17",
   "group": "API & Extensibility",
   "capability": "Query/mutate workspace data via REST or GraphQL API generated per-tenant from the schema",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "/rest/ and /graphql/",
    "mcp": null,
    "cli": null,
    "ui": "Settings → API & Webhooks → API docs/playground"
   },
   "check": "Authenticated GraphQL query against a custom object returns schema-matching data in the playground",
   "source": "https://docs.twenty.com/developers/extend/api.md"
  },
  {
   "id": "cap-18",
   "group": "API & Extensibility",
   "capability": "Manage data model (objects/fields/relations) programmatically via the Metadata API",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "/rest/metadata/ and /metadata/",
    "mcp": null,
    "cli": null,
    "ui": "Settings → Data Model"
   },
   "check": "POST to /rest/metadata/objects creates an object visible in Settings → Data Model without UI interaction",
   "source": "https://docs.twenty.com/developers/extend/api.md"
  },
  {
   "id": "cap-19",
   "group": "API & Extensibility",
   "capability": "Receive real-time record change notifications via outgoing webhooks",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /rest/webhooks (register)",
    "mcp": null,
    "cli": null,
    "ui": "Settings → API & Webhooks → Webhooks"
   },
   "check": "Registered webhook endpoint receives an HTTP POST payload when the subscribed record event occurs",
   "source": "https://docs.twenty.com/developers/extend/api.md; https://docs.twenty.com/getting-started/key-features.md"
  },
  {
   "id": "cap-20",
   "group": "API & Extensibility",
   "capability": "Authorize external apps on behalf of a user via OAuth",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "/oauth endpoints",
    "mcp": "OAuth login flow for MCP",
    "cli": null,
    "ui": "OAuth consent screen"
   },
   "check": "OAuth-issued token successfully authenticates a REST/GraphQL/MCP call scoped to the authorizing user",
   "source": "https://docs.twenty.com/developers/extend/api.md; https://docs.twenty.com/user-guide/ai/capabilities/mcp.md"
  },
  {
   "id": "cap-21",
   "group": "AI",
   "capability": "Connect any MCP-compatible AI client (Claude, Cursor, ChatGPT) to read/write CRM data via natural language",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": "find_many_{object}, find_one_{object}, update_one_{object}, create_one_{object}, learn_tools, get_tool_catalog",
    "cli": null,
    "ui": "Settings → MCP & APIs → MCP"
   },
   "check": "MCP client call to create_one_person is reflected as a new record in the Twenty UI",
   "source": "https://docs.twenty.com/user-guide/ai/capabilities/mcp.md"
  },
  {
   "id": "cap-22",
   "group": "Apps",
   "capability": "Extend Twenty with a custom app package (custom objects, server-side logic, UI components, AI agents as TypeScript code)",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": "Twenty CLI app scaffold/build commands",
    "ui": null
   },
   "check": "Deployed app's custom UI component/object appears and functions inside the workspace",
   "source": "https://docs.twenty.com/developers/extend/apps/getting-started/quick-start.md; https://twenty.com/pricing"
  },
  {
   "id": "cap-23",
   "group": "Permissions & Access",
   "capability": "Create roles and assign object/field/settings-level permissions to members",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "REST/GraphQL role metadata",
    "mcp": null,
    "cli": null,
    "ui": "Settings → Members → Roles"
   },
   "check": "A member assigned a restricted role cannot view/edit the fields or objects excluded from their role",
   "source": "https://docs.twenty.com/user-guide/permissions-access/overview.md"
  },
  {
   "id": "cap-24",
   "group": "Permissions & Access",
   "capability": "Restrict access at the individual record level (row-level permissions)",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Settings → Members → Roles → record-level rules"
   },
   "check": "A restricted user's object view omits records outside their assigned scope",
   "source": "https://twenty.com/pricing"
  },
  {
   "id": "cap-25",
   "group": "Permissions & Access",
   "capability": "Enable two-factor authentication for a user account",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Settings → Security → Two-factor authentication"
   },
   "check": "Login requires a second factor after enabling, confirmed on next sign-in",
   "source": "https://twenty.com/pricing"
  },
  {
   "id": "cap-26",
   "group": "Permissions & Access",
   "capability": "Review audit logs of who did what in the workspace",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Settings → Security → Audit Logs"
   },
   "check": "Audit log entry appears timestamped to a specific user action (e.g. record delete)",
   "source": "https://twenty.com/pricing"
  },
  {
   "id": "cap-27",
   "group": "Self-Hosting",
   "capability": "Self-host the full Twenty instance via Docker Compose",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": "docker compose up",
    "ui": null
   },
   "check": "Self-hosted instance responds at the configured domain and allows login",
   "source": "https://docs.twenty.com/developers/self-host/capabilities/docker-compose.md; https://docs.twenty.com/getting-started/key-features.md"
  },
  {
   "id": "cap-28",
   "group": "Account Admin",
   "capability": "Configure SSO (SAML/OIDC) for workspace login",
   "weight": "peripheral",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Settings → Security → SSO"
   },
   "check": "Login redirects to the configured identity provider and succeeds for a provisioned user",
   "source": "https://twenty.com/pricing; https://docs.twenty.com/user-guide/permissions-access/capabilities/sso-configuration.md"
  },
  {
   "id": "cap-29",
   "group": "Account Admin",
   "capability": "Set a custom domain for the workspace",
   "weight": "peripheral",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Settings → Domain"
   },
   "check": "Workspace loads under the configured custom domain instead of the default *.twenty.com URL",
   "source": "https://twenty.com/pricing"
  },
  {
   "id": "cap-30",
   "group": "Account Admin",
   "capability": "Provision users automatically via SCIM",
   "weight": "peripheral",
   "plan": "paid",
   "surfaces": {
    "api": "SCIM endpoint",
    "mcp": null,
    "cli": null,
    "ui": "Settings → Security → SCIM (Enterprise)"
   },
   "check": "A user created in the IdP appears automatically as a workspace member without manual invite",
   "source": "https://twenty.com/pricing"
  },
  {
   "id": "cap-31",
   "group": "Account Admin",
   "capability": "Restrict workspace network access via IP allow-listing",
   "weight": "peripheral",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Settings → Security (Enterprise)"
   },
   "check": "A login attempt from a non-allow-listed IP is blocked",
   "source": "https://twenty.com/pricing"
  },
  {
   "id": "cap-32",
   "group": "Account Admin",
   "capability": "Support multiple environments (local/production) for building and testing changes",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Environment switcher"
   },
   "check": "Changes made in a local environment do not appear in production until promoted",
   "source": "https://twenty.com/pricing"
  }
 ],
 "attempts": [
  {
   "t": "00:24",
   "cap": "docs",
   "capability": "find docs",
   "task": "Find agent docs",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "twenty.com/llms.txt and docs.twenty.com/llms.txt 200 text/plain; describe MCP at /mcp, REST /rest, GraphQL, per-workspace OpenAPI, explicit agent-signup policy (ToS sec 10), signup CAPTCHA-protected via app.twenty.com",
   "notes": "Excellent agent-facing docs"
  },
  {
   "t": "01:51",
   "cap": "signup",
   "capability": "sign up",
   "task": "Create account with email+password on app.twenty.com",
   "route": "browser",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "After Sign up page shows Check your Emails: verification email sent to the agent's inbox",
   "notes": "Invisible reCAPTCHA (v3/enterprise-style, recaptcha signal true, no visible challenge) passed our agent's browser. No headless signup API documented; llms.txt says signup is web-only by design."
  },
  {
   "t": "06:32",
   "cap": "verify",
   "capability": "verify email",
   "task": "Open verification link from inbox",
   "route": "browser",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "Mail arrived <1 min. Opening link in the profile showed Email Verification Failed: You must be authenticated to perform this action; signing in with email+password afterwards went straight to Create workspace, so the account counted as verified",
   "notes": "Confusing failure message on the verify page even though the address was accepted"
  },
  {
   "t": "06:32",
   "cap": "signup",
   "capability": "workspace onboarding",
   "task": "Create workspace, skip sync/apps/invite, choose plan",
   "route": "browser",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "Workspace agentdrives-drive015.twenty.com created; plan-required screen offered Upgraded (30 days, card) or Basic without credit card 7 days; chose Basic no-card, landed on Companies list with 5 seed companies",
   "notes": "hCaptcha script present on plan-required page (invisible, no challenge shown)"
  },
  {
   "t": "10:16",
   "cap": "credentials",
   "capability": "API key",
   "task": "Create API key in Settings > MCP & APIs > API",
   "route": "browser",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "Key agentdrives (Admin role, never expires) created; shown once, regenerated with typed yes confirmation to capture; GET /rest/companies with Bearer returned 200",
   "notes": "No documented headless way to mint the first key; MCP OAuth 2.1 is the alternative (discovery at /.well-known/oauth-protected-resource)"
  },
  {
   "t": "10:16",
   "cap": "first_call",
   "capability": "first API call",
   "task": "GET /rest/companies?limit=2 and fetch per-workspace OpenAPI",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "200 with seed companies; /rest/open-api/core 200 (322 paths), /rest/open-api/metadata 200 (27 paths)",
   "notes": ""
  },
  {
   "t": "11:42",
   "cap": "first_action",
   "capability": "first real action",
   "task": "Create a company via MCP execute_tool create_one_company",
   "route": "mcp",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "MCP returned id 49f2f6f5-...; GET /rest/companies/{id} returns it",
   "notes": "First try failed with clear error: Object company does not have any employees field"
  },
  {
   "t": "11:42",
   "cap": "cap-01",
   "capability": "CRUD CRM record",
   "task": "Create company via MCP, update its name via MCP update_one_company, create person+opportunity via REST POST, PATCH opportunity stage",
   "route": "mcp",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "GET /rest/companies/49f2f6f5... name=AgentDrives Test Co (updated); PATCH /rest/opportunities/d2a8fe19... returned stage MEETING",
   "notes": "First MCP call with guessed field employees failed with a precise error; delete verified later in cleanup"
  },
  {
   "t": "11:42",
   "cap": "cap-21",
   "capability": "MCP client read/write",
   "task": "Connect to /mcp with API key Bearer, initialize, tools/list, create a company",
   "route": "mcp",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "initialize 200 (Twenty MCP Server 0.1.0, streamable-http SSE); tools/list = 7 meta tools; get_tool_catalog lists 324 tools (235 CRUD, 22 workflow, 22 view, 13 metadata, 7 dashboard, 7 role, 4 webhook); create_one_company via execute_tool reflected in REST",
   "notes": "Lazy tool loading: learn_tools/execute_tool pattern; 16 skills via load_skills"
  },
  {
   "t": "11:42",
   "cap": "cap-03",
   "capability": "relations",
   "task": "Create person and opportunity with companyId, read company with depth=1",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "GET /rest/companies/{id}?depth=1 shows people [AgentDrives Test] and opportunities [AgentDrives pilot 1000 EUR]",
   "notes": ""
  },
  {
   "t": "11:42",
   "cap": "cap-02",
   "capability": "custom object + fields",
   "task": "POST /rest/metadata/objects testDrive, POST /rest/metadata/fields agentScore NUMBER and company MANY_TO_ONE relation, create a record at /rest/testDrives",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "GET /rest/metadata/objects lists testDrive; POST /rest/testDrives worked immediately; GraphQL testDrives returns agentScore 42 and company relation",
   "notes": "Metadata responses wrap data as an array/object directly rather than data.objects - differs from what I expected from docs"
  },
  {
   "t": "11:42",
   "cap": "cap-18",
   "capability": "metadata API",
   "task": "Create object/fields programmatically",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "same as object b15b2995... active, new REST/GraphQL endpoints live within seconds",
   "notes": ""
  },
  {
   "t": "11:42",
   "cap": "cap-17",
   "capability": "REST/GraphQL per tenant",
   "task": "GraphQL query on custom object testDrives with nested company",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /graphql {testDrives{edges{node{name agentScore company{name}}}}} returned Drive 015, 42, AgentDrives Test Co (updated)",
   "notes": "Same Bearer key works for REST, GraphQL, metadata and MCP"
  },
  {
   "t": "12:33",
   "cap": "cap-14",
   "capability": "bulk via API",
   "task": "POST /rest/batch/people with 3 records",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "Response returned 3 ids; GET /rest/people?filter=name.firstName[eq]:Batch totalCount 3",
   "notes": "Did not test the 60-record limit (no volume by design)"
  },
  {
   "t": "12:33",
   "cap": "cap-15",
   "capability": "notes",
   "task": "POST /rest/notes with bodyV2.markdown, link via POST /rest/noteTargets to company",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "GET /rest/noteTargets?filter=noteId[eq]:20617a08... shows targetCompanyId 49f2f6f5...",
   "notes": "Linking needs a second call to the junction object noteTargets"
  },
  {
   "t": "12:33",
   "cap": "cap-16",
   "capability": "tasks",
   "task": "Create task assigned to workspace member, link to person, mark DONE",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "GET /rest/tasks/ee16c808...?depth=1 status DONE, assigneeId c4dbca74..., taskTargets person e5a01198...",
   "notes": ""
  },
  {
   "t": "12:33",
   "cap": "cap-04",
   "capability": "saved view",
   "task": "MCP create_view KANBAN on opportunity grouped by stage, add filter amount>=500 and sort amount DESC",
   "route": "mcp",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "get_view_query_parameters returns filter amountMicros gte 500000000, orderBy amount DescNullsLast; GET /rest/metadata/views/938e3664... returns the view",
   "notes": "Filter value in currency units is converted to micros automatically"
  },
  {
   "t": "14:50",
   "cap": "cap-05",
   "capability": "build workflow",
   "task": "MCP create_complete_workflow: person.created -> create task -> create note, activate",
   "route": "mcp",
   "documented": true,
   "result": "failed",
   "verified": true,
   "evidence": "First call rejected: Step configuration is invalid - id: Invalid UUID (tool schema does not say step ids must be UUIDs); the failed call still left an orphan DRAFT workflow 2d93651a... behind",
   "notes": "Not atomic: failed create leaves a draft"
  },
  {
   "t": "14:50",
   "cap": "cap-05",
   "capability": "build workflow",
   "task": "Retry with UUID step ids",
   "route": "mcp",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "Workflow 1be92d1b... ACTIVE with 2 steps per GET /rest/workflows; run #1 COMPLETED",
   "notes": "Worked on the 7-day no-card trial (Basic); map marks workflows as paid"
  },
  {
   "t": "14:50",
   "cap": "cap-06",
   "capability": "trigger workflow",
   "task": "Create a person via REST to fire DATABASE_EVENT person.created",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "GET /rest/workflowRuns: #1 - AgentDrives welcome COMPLETED, trigger result recordId cfbf18a0... (the person just created), started 1s after creation",
   "notes": "Webhook/manual/cron triggers not tested"
  },
  {
   "t": "14:50",
   "cap": "cap-07",
   "capability": "chain actions",
   "task": "Two chained CREATE_RECORD steps using trigger variables",
   "route": "mcp",
   "documented": true,
   "result": "partial",
   "verified": true,
   "evidence": "Both steps SUCCESS in run state, task and note created in order, but title is Welcome undefined (wf): the variable syntax {{trigger.object.name.firstName}} given in the MCP tool description resolves to undefined; the actual trigger output is under properties.after.name.firstName",
   "notes": "Docs-vs-reality mismatch in the MCP tool description. HTTP/code/AI/branch steps not tested"
  },
  {
   "t": "14:50",
   "cap": "cap-19",
   "capability": "webhooks",
   "task": "MCP create_webhook for person.created to our agent.agentdrives.com URL, create a person to fire it",
   "route": "mcp",
   "documented": true,
   "result": "partial",
   "verified": false,
   "evidence": "Webhook 2add6f79... listed by GET /rest/metadata/webhooks with a signing secret; delivery could not be confirmed because we had no readable receiver",
   "notes": "We: no receiver logs available. Registration verified, delivery not"
  },
  {
   "t": "14:51",
   "cap": "cap-23",
   "capability": "roles",
   "task": "MCP create_role Agent read-only (read all, no update/delete/settings)",
   "route": "mcp",
   "documented": true,
   "result": "partial",
   "verified": true,
   "evidence": "GraphQL /metadata getRoles lists Agent read-only with canUpdateAllObjectRecords false",
   "notes": "Enforcement not tested: would need a second member or a second key with that role"
  },
  {
   "t": "15:42",
   "cap": "cap-11",
   "capability": "dashboard",
   "task": "MCP create_complete_dashboard with a GRAPH AGGREGATE_CHART COUNT of people",
   "route": "mcp",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "Dashboard bbd8aca0... renders People count = 11 in the browser; GET /rest/people totalCount 11",
   "notes": ""
  },
  {
   "t": "16:59",
   "cap": "cap-08",
   "capability": "AI chatbot",
   "task": "Ask AI in the web UI: how many people have first name Batch, list last names",
   "route": "browser",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "Chat answered 3 matches: One, Three, Two - same as GET /rest/people?filter=name.firstName[eq]:Batch totalCount 3",
   "notes": "No documented API/MCP tool to talk to the built-in AI chat; agents can use MCP directly instead. Chat also had an onboarding question pending"
  },
  {
   "t": "17:54",
   "cap": "cap-20",
   "capability": "OAuth",
   "task": "Dynamic client registration at /oauth/register, PKCE authorize (consent click in browser), token exchange, call REST and MCP with the token",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "RFC 8414 metadata at /.well-known/oauth-authorization-server; DCR returned client_id; consent screen Connect AgentDrives drive to your account; token scope api profile expires_in 1800; GET /rest/companies with OAuth token 200; MCP call authenticated (returned a tool validation error Select is required, not an auth error)",
   "notes": "Only the consent click needs a logged-in browser; the rest is headless. MCP find_many_people needs an explicit select parameter"
  },
  {
   "t": "20:25",
   "cap": "pay",
   "capability": "pay step",
   "task": "Probe agent payment rails and the in-app purchase path",
   "route": "browser",
   "documented": true,
   "result": "blocked",
   "verified": true,
   "evidence": "x402./mpp./agents.twenty.com 404 JSON; /.well-known/ucp, /auth.md, /SKILL.md 404 HTML; unauthenticated /rest/companies 403 Missing authentication token (no 402); developer docs only mention app credits, no billing API. In-app: Settings > Billing shows Pro plan Trial, $12/seat/month, Subscribe Now -> modal Add your credit card -> Add credit card; clicking it in our agent's browser opened nothing (no navigation, no popup, no Stripe request seen); hCaptcha script present on the page",
   "notes": "Card-at-checkout purchase via web UI only; we did not enter or reach a card form. 7-day Pro trial needs no card; 30-day trial needs billing details"
  },
  {
   "t": "20:32",
   "cap": "cap-24",
   "capability": "Row-level permissions",
   "task": "Check availability on the trial plan",
   "route": "none",
   "documented": true,
   "result": "plan_gated",
   "verified": true,
   "evidence": "twenty.com/pricing comparison table: Row-level permissions not in Pro, included in Organization ($19/user/month); our workspace is on the Pro plan trial (Settings > Billing)",
   "notes": ""
  },
  {
   "t": "20:32",
   "cap": "cap-26",
   "capability": "Audit logs",
   "task": "Check availability on the trial plan",
   "route": "none",
   "documented": true,
   "result": "plan_gated",
   "verified": true,
   "evidence": "twenty.com/pricing comparison table: Audit logs not in Pro, included in Organization; our workspace is on the Pro plan trial (Settings > Billing)",
   "notes": ""
  },
  {
   "t": "20:32",
   "cap": "cap-28",
   "capability": "SAML/OIDC SSO",
   "task": "Check availability on the trial plan",
   "route": "none",
   "documented": true,
   "result": "plan_gated",
   "verified": true,
   "evidence": "twenty.com/pricing comparison table: SAML/OIDC SSO not in Pro, included in Organization; our workspace is on the Pro plan trial (Settings > Billing)",
   "notes": ""
  },
  {
   "t": "20:32",
   "cap": "cap-29",
   "capability": "Custom domain",
   "task": "Check availability on the trial plan",
   "route": "none",
   "documented": true,
   "result": "plan_gated",
   "verified": true,
   "evidence": "twenty.com/pricing comparison table: Custom domain not in Pro, included in Organization; our workspace is on the Pro plan trial (Settings > Billing)",
   "notes": ""
  },
  {
   "t": "20:32",
   "cap": "cap-30",
   "capability": "SCIM provisioning",
   "task": "Check availability on the trial plan",
   "route": "none",
   "documented": true,
   "result": "plan_gated",
   "verified": true,
   "evidence": "twenty.com/pricing comparison table: SCIM provisioning not in Pro, included in Enterprise (from $50k/year); our workspace is on the Pro plan trial (Settings > Billing)",
   "notes": ""
  },
  {
   "t": "20:33",
   "cap": "cap-31",
   "capability": "IP allow-listing",
   "task": "Check availability on the trial plan",
   "route": "none",
   "documented": true,
   "result": "plan_gated",
   "verified": true,
   "evidence": "twenty.com/pricing comparison table: IP allow-listing not in Pro, included in Enterprise; our workspace is on the Pro plan trial (Settings > Billing)",
   "notes": ""
  },
  {
   "t": "23:06",
   "cap": "cap-09",
   "capability": "AI agent in workflow",
   "task": "Workflow company.created -> AI_AGENT classify -> create note with the response, all via MCP",
   "route": "mcp",
   "documented": true,
   "result": "failed",
   "verified": true,
   "evidence": "create_complete_workflow with an AI_AGENT step refused: AI_AGENT steps cannot be created via create_complete_workflow ... Use create_workflow_version_step instead, then call update_agent",
   "notes": "Clear, actionable error"
  },
  {
   "t": "23:06",
   "cap": "cap-09",
   "capability": "AI agent in workflow",
   "task": "Retry: create_workflow_version_step AI_AGENT, update_agent prompt, update_workflow_version_step, add CREATE_RECORD step, activate, create a company",
   "route": "mcp",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "Run #1 - AgentDrives AI summary COMPLETED; AI step response Likely an AI research and software company...; GET /rest/notes shows note AI: Likely an AI research...",
   "notes": "Gotchas: create_workflow_version_step ignored defaultSettings for CREATE_RECORD (defaulted to objectName company - a self-retriggering loop risk on a company.created trigger); activate_workflow_version succeeded and validate_workflow passed although that step was valid:false; active versions cannot be edited, need create_draft_from_workflow_version. Used 0.5 trial credits pool"
  },
  {
   "t": "23:06",
   "cap": "cap-10",
   "capability": "connect Google/Microsoft mailbox",
   "task": "Connect a mailbox during onboarding",
   "route": "browser",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "Onboarding /sync/emails offers only Continue with Google / Continue with Microsoft OAuth",
   "notes": "We have no Google Workspace or Microsoft 365 account; IMAP not offered in onboarding. Not a product failure"
  },
  {
   "t": "23:06",
   "cap": "cap-12",
   "capability": "CSV import",
   "task": "CSV import",
   "route": "none",
   "documented": true,
   "result": "skipped",
   "verified": false,
   "evidence": "",
   "notes": "UI-only file upload wizard; not reached within the 45-minute budget"
  },
  {
   "t": "23:06",
   "cap": "cap-13",
   "capability": "Export view to CSV",
   "task": "Export view to CSV",
   "route": "none",
   "documented": true,
   "result": "skipped",
   "verified": false,
   "evidence": "",
   "notes": "UI-only; not reached within the budget"
  },
  {
   "t": "23:06",
   "cap": "cap-25",
   "capability": "Two-factor authentication",
   "task": "Two-factor authentication",
   "route": "none",
   "documented": true,
   "result": "skipped",
   "verified": false,
   "evidence": "",
   "notes": "UI-only; not reached within the budget"
  },
  {
   "t": "23:06",
   "cap": "cap-22",
   "capability": "Custom app package via CLI",
   "task": "Custom app package via CLI",
   "route": "none",
   "documented": true,
   "result": "skipped",
   "verified": false,
   "evidence": "",
   "notes": "not attempted within the budget"
  },
  {
   "t": "23:07",
   "cap": "cap-27",
   "capability": "Self-host via Docker",
   "task": "Self-host via Docker",
   "route": "none",
   "documented": true,
   "result": "skipped",
   "verified": false,
   "evidence": "",
   "notes": "hosted product did not block us, so self-host was optional; skipped for time"
  },
  {
   "t": "23:07",
   "cap": "cap-32",
   "capability": "Multiple environments",
   "task": "Multiple environments",
   "route": "none",
   "documented": true,
   "result": "skipped",
   "verified": false,
   "evidence": "",
   "notes": "not attempted within the budget"
  },
  {
   "t": "23:22",
   "cap": "cap-01",
   "capability": "delete record",
   "task": "DELETE /rest/people/{id} then GET",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "DELETE 200; GET /rest/people/e5a01198... 404 Record not found",
   "notes": "Also deleted 3 workflows, webhook and view via REST/MCP, all 200"
  },
  {
   "t": "24:57",
   "cap": "cancel",
   "capability": "cancel plan",
   "task": "Cancel the trial",
   "route": "browser",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "Settings > Billing shows Cancel Plan (Your workspace will be disabled); we removed the trial by deleting the workspace: afterwards the API returns 401 WORKSPACE_NOT_FOUND",
   "notes": "No card was ever added, so nothing recurring. No billing API; cancel is web UI only"
  },
  {
   "t": "24:57",
   "cap": "delete",
   "capability": "delete account",
   "task": "Settings > General > Delete workspace, type email to confirm",
   "route": "browser",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "Redirected to app.twenty.com/welcome; GET /rest/companies with the old key -> 401 Workspace not found. Signing in again afterwards led to the sign-up path (Check your Emails), suggesting the user was removed with its only workspace",
   "notes": "No documented API for workspace/account deletion. Our re-login check created a pending unverified sign-up for the same address (not verified, no workspace)"
  }
 ],
 "stale": false,
 "icon": "/logos/twenty.png",
 "monitored": false,
 "verdict": "Runs on its own: L4 · Runs on its own. Signup, onboarding and the first key need a browser, and invisible reCAPTCHA let our agent through with no challenge shown. Paying is where it stopped: a trial starts without a card, but clicking add credit card at checkout did nothing in our agent's browser, so a person has to add the card. Short of that, Twenty worked headless: REST and an official MCP server let it create a company and read it back, with tools covering records, custom objects, views and workflows. Cancelling and deleting the workspace both worked on their own, with no card ever added.",
 "page": "https://agentdrives.com/tools/twenty?via=api"
}