Skip to content

Managed Applications

Managed Applications are optional applications that ThinkWork provisions and operates inside the same AWS deployment. They are not end-user connector settings. They are infrastructure controls for operators who can change the stage deployment through the normal GitHub Actions and Terraform pipeline.

Surface: Spaces/Desktop Settings -> General -> Managed Applications and Settings -> Plugins
Primary files: apps/web/src/components/settings/ManagedApplicationsSection.tsx, packages/api/src/graphql/resolvers/core/managedApplications.ts

The first managed applications are:

ApplicationPurposeSettings page appears when
CogneeKnowledge Graph substrate for ontology workDeployment status reports Cognee running
Twenty CRMSelf-hosted CRM runtime managed by ThinkWorkDeployment status reports Twenty running
PlaneSelf-hosted project management runtimePlugin is installed and runtime is deployed

The Managed Applications section is visible only to operators. Members do not see deployment controls, and app-specific settings pages remain hidden until deployment status reports the runtime as enabled.

ThinkWork exposes three lifecycle actions for retained managed applications:

ActionEffect
DeployProvisions retained infrastructure and starts the app runtime
ParkStops runtime capacity while retaining app data, endpoint wiring, secrets, and MCP path
DestroyRemoves runtime infrastructure, retained storage/cache, secrets, DB state, and MCP rows

The deployed status still resolves to the retained/runtime state:

ProvisionedRuntime enabledMeaning
falsefalseNever enabled; no retained app resources exist
truetrueRuntime is running and the app settings page is visible
truefalseRuntime is parked; retained resources and repair path remain

Parking Twenty stops the server and worker runtime capacity while retaining the dedicated database, Secrets Manager values, persistent file storage, cache configuration, DNS path, and re-enable path.

Parking Plane stops web/API, worker, beat-worker, and live runtime capacity while retaining work items, pages, comments, files, database credentials, RabbitMQ, cache, S3 storage, endpoint wiring, and user activation records.

Destroying Twenty is intentionally separate from parking. It queues a destructive deploy that tears down the Twenty infrastructure and then removes the dedicated Twenty database, database role, and Twenty Secrets Manager entries. Use it only when CRM data is no longer needed.

Destroying Plane is also separate from parking. It removes the retained Plane runtime substrate and app-owned data paths, including database state, file storage, queue/cache resources, secrets, and managed MCP rows. Use it only when Plane work-item history is no longer needed.

Cognee follows the existing optional Knowledge Graph lifecycle. Its deploy control now lives in Managed Applications; the Knowledge Graph settings page is for operational details and health once Cognee is running.

Twenty CRM v1 is a deployable managed app, not a custom ThinkWork CRM product. When enabled, Terraform provisions:

  • public HTTPS access at the managed CRM host;
  • ECS/Fargate server and worker services;
  • a dedicated Twenty database and role on the existing Aurora/Postgres instance;
  • ElastiCache Valkey/Redis-compatible cache;
  • persistent file storage and CloudWatch logs;
  • Secrets Manager entries for the database URL and Twenty encryption key.

The CRM settings page shows the public URL, stage, region, service names, log groups, load balancer/target group identifiers, and a /healthz connection test.

Twenty v1 uses Twenty’s native first-user setup. After the runtime is deployed, open the CRM URL from Settings -> CRM and complete Twenty’s first workspace admin flow there.

ThinkWork does not pre-seed CRM users, invites, or workspaces in v1.

ThinkWork SSO/Cognito/Google integration for Twenty is documented as follow-up work after the smallest deployable release. The CRM settings page should show that SSO is deferred rather than exposing inactive SSO controls.

Other deferred work includes richer CRM connector workflows, write-policy design for CRM mutations, and a first-class CRM extension inside ThinkWork.

When Twenty CRM is running, ThinkWork reconciles a system-managed MCP server named Twenty CRM into Settings -> MCP Servers. Operators should not add a second manual Twenty MCP row. Use the CRM settings page only to install or repair the managed MCP registration when an already-running stage is missing the row.

Managed Applications and MCP Servers intentionally split responsibilities:

SurfaceResponsibility
Settings -> General -> Managed ApplicationsDeploy, park, destroy, and recover managed application infrastructure
Settings -> CRMInspect CRM runtime state and repair the managed MCP registration
Settings -> MCP ServersLet each user connect, reconnect, or clear their own Twenty MCP auth

Parking Twenty disables runtime availability for the managed MCP connector but keeps the MCP row and per-user token records so reconnect continuity survives a redeploy. Destructive Destroy removes the managed MCP row and token material as part of full CRM cleanup.

When the managed MCP row is installed or repaired, ThinkWork assigns it to the tenant platform default agent. That makes the connector available to runtime only after the current user has completed their own OAuth connection.

Plane is installed from Settings -> Plugins as the plane application plugin. The plugin detail page is the operator entry point for install/uninstall and infrastructure lifecycle. The backing managed-app adapter is not meant to be manually duplicated from the generic Managed Applications list.

Plane MCP uses a user-provided Plane PAT and workspace header instead of OAuth. Each user connects their own Plane account by activating the plugin with:

CredentialSent to Plane asNotes
Plane personal access tokenBearer tokenStored as a user-scoped activation secret
Plane workspace slugx-workspace-slugStored with the same activation

The activation belongs to the signed-in user. Operators should not paste a tenant-wide Plane API key into plugin setup, and agents should not borrow a token from another user. When the current user has no active Plane activation, runtime MCP assembly fails closed for Plane instead of falling back to shared credentials.

After the deploy workflow finishes, run the managed-app smoke from the repo root:

Terminal window
node plugins/twenty/smoke/twenty-managed-app-smoke.mjs
SMOKE_ENABLE_TWENTY_MANAGED_APP=1 \
SMOKE_TENANT_ID=<tenant-id> \
node plugins/twenty/smoke/twenty-managed-app-smoke.mjs

Dry-run mode prints the live-mode requirements and exits successfully. Live mode reads Terraform outputs and, when GraphQL credentials are available, deployment status. If Twenty is not provisioned, the smoke skips with a clear message. If Twenty is running, it requires an HTTPS URL and probes the public /healthz endpoint.

After the CRM runtime is healthy and the user has connected Twenty from Settings -> MCP Servers, run the MCP OAuth smoke:

Terminal window
node plugins/twenty/smoke/twenty-mcp-oauth-smoke.mjs
SMOKE_ENABLE_TWENTY_MCP_OAUTH=1 \
SMOKE_API_BASE_URL=<api-url> \
SMOKE_COGNITO_ID_TOKEN=<current-user-id-token> \
SMOKE_TENANT_ID=<tenant-id> \
SMOKE_USER_ID=<user-id> \
SMOKE_AGENT_ID=<agent-id> \
node plugins/twenty/smoke/twenty-mcp-oauth-smoke.mjs

Dry-run mode prints the required live-mode inputs. Live mode verifies Twenty OAuth metadata, the system-managed MCP row, the current user’s connected auth status, and the ThinkWork MCP proxy tools/list path. Set SMOKE_TWENTY_MCP_CALL=1 plus SMOKE_TWENTY_USER_EMAIL or SMOKE_TWENTY_WORKSPACE_MEMBER_ID to run the required assigned-opportunities tool proof through ThinkWork’s runtime credential injection path:

Terminal window
SMOKE_ENABLE_TWENTY_MCP_OAUTH=1 \
SMOKE_TWENTY_MCP_CALL=1 \
SMOKE_TWENTY_USER_EMAIL=<twenty-user-email> \
SMOKE_API_BASE_URL=<api-url> \
SMOKE_COGNITO_ID_TOKEN=<current-user-id-token> \
SMOKE_TENANT_ID=<tenant-id> \
SMOKE_USER_ID=<user-id> \
SMOKE_AGENT_ID=<agent-id> \
node plugins/twenty/smoke/twenty-mcp-oauth-smoke.mjs

After Plane is healthy and a user has activated the plugin, run:

Terminal window
node plugins/plane/smoke/plane-mcp-smoke.mjs
SMOKE_ENABLE_PLANE_MCP=1 \
SMOKE_PLANE_MCP_WRITE=1 \
SMOKE_PLANE_MCP_URL=https://plane.example.com/mcp \
SMOKE_PLANE_API_KEY=<plane-pat> \
SMOKE_PLANE_WORKSPACE_SLUG=<workspace-slug> \
node plugins/plane/smoke/plane-mcp-smoke.mjs

Use SMOKE_PLANE_THINKWORK_PROXY=1 with an activated Cognito user token to verify the ThinkWork /api/mcp proxy path and per-user bearer plus header injection. Keep SMOKE_PLANE_MCP_WRITE unset for read-only checks.