# Auth Source: https://trytilde.ai/docs/auth # Tilde auth.md Applications with their own login system should use [organization runtime identities and proxy tokens](/docs/identities/index). Runtime identities can exist without a login account; managed linking connects a verified Tilde account later. Tilde supports anonymous, agent-first registration followed by an optional human claim. An agent can create a temporary Tilde organization without waiting for a person to sign in, use the returned agent API key, and later transfer the temporary workspace and its supported resources to a human-owned organization. This flow issues an API key directly. It is not an OAuth identity-assertion or token-exchange flow. ## Actors and credentials Tilde has two first-class actor types: **human** and **agent**. Credential form does not determine actor type by itself: * An API key authenticates as its owning runtime identity. A personal identity key remains human; an agent or installation key remains agent. * An OAuth access token is a bearer token and authenticates a human. * A request must carry exactly one credential form. Sending both `x-api-key` and `Authorization: Bearer ...` is rejected. Organization proxy tokens provide explicit application delegation through `X-Tilde-Proxy-Token` and `X-Tilde-Identity-Id`. Tilde checks the token's organization/capabilities and the effective identity's current membership and resource permissions. The token issuer's administrative roles are never combined with the identity's permissions. Revoking a credential does not delete its runtime identity. ## Resource visibility and ownership Tilde authorization-bearing resources have two independent access planes: * **Visibility** controls discovery, listing, reading, and using the resource or its inherited content. * **Ownership** controls settings, membership, lifecycle operations, deletion, and grant management. Each plane is either `team` or `private`. For a team-scoped resource, `team` admits current members of that team. For a personal resource without a team ID, it admits current members of the containing organization. `private` admits only explicitly granted Identity users and groups from the same tenant. Visibility and ownership never imply one another. An administrator or ownership grantee can manage a private resource without being able to read its content unless the visibility plane also admits them. Lists are filtered before pagination, and direct reads return not found or authorization errors when visibility is absent. New private resources retain an effective-creator grant. Tilde commits validated initial grants with the resource and prevents removal of the last private ownership grant. Group access follows current Identity membership, so removing a user from the group or tenant stops authorizing future requests. ### Standard authorization operations Authorization-bearing REST roots use the same operation family under their team or personal resource path: ```text theme={"system"} POST /{resource_id}/visibility { "mode": "team" | "private" } POST /{resource_id}/ownership { "mode": "team" | "private" } GET /{resource_id}/{plane}/grants POST /{resource_id}/{plane}/grants { "principal_type": "user" | "group", "principal_id": "..." } DELETE /{resource_id}/{plane}/grants/{principal_type}/{principal_id} ``` The exact root path is published in the [OpenAPI specification](https://trytilde.ai/openapi.json). Grant listing and mutation require ownership access. Re-adding or removing the same grant is idempotent, subject to the last-private-owner guard. Common-provider installations are authorization roots for provider bundles. Their policy is initialized from the source resource-server credential, then becomes the live policy inherited by the generated MCP, ChatKit, Signals, and reverse-proxy surfaces. Change a bound surface's visibility, ownership, or grants through the installation endpoints; sibling surfaces do not copy policy from one another. Operations spanning independent roots require every applicable visibility check. For example, an MCP invocation requires both server and tool visibility, a signal delivery requires provider and rule visibility, and chat content requires the provider or agent plus session visibility. Billing entitlements and encryption key records are infrastructure, not shareable roots, so they do not expose these mode/grant operations. Resource secret use receives a server-only capability bound to the exact resource, action, and encryption scope after domain authorization. These checks are enforced by the authenticated API and tenant-scoped persistence queries. Database row-level security is planned as an additional defense-in-depth layer; it is not currently the public authorization boundary. ## Register anonymously Send an unauthenticated request to: ```http theme={"system"} POST https://api.trytilde.ai/api/v1/identity/temporary-accounts Content-Type: application/json ``` Both fields are optional: ```json theme={"system"} { "label": "code review agent", "human_email": "owner@example.com" } ``` A successful response creates a temporary organization, team, and agent user. It returns: * `org_id` and `team_id` * `api_key` and `api_key_id` * `claim_url` and a six-digit `claim_pin` * `claim_token_expires_at` and `expires_at` The temporary account lasts 24 hours. The initial claim URL lasts one hour. In production, the claim URL opens the human claim page under `https://trytilde.ai/app/temporary-accounts/claim/` while the authenticated claim API remains on `https://api.trytilde.ai`. ## Use the credential Send the returned API key in the `x-api-key` header: ```http theme={"system"} GET https://api.trytilde.ai/api/v1/identity/auth/whoami x-api-key: ``` You can also connect to the Tilde Global MCP server at `https://api.trytilde.ai/mcp` with the same header. Call `tilde_whoami` first and use its `team_id` for team-scoped tools. Store the API key, claim URL, and PIN as secrets. Do not commit them, include them in logs, or send them to anyone other than the intended owner. ## Refresh an expired claim URL If the claim URL expires while the temporary account is still active, create a new one with the temporary API key: ```http theme={"system"} POST https://api.trytilde.ai/api/v1/identity/temporary-accounts/claim-url x-api-key: ``` The six-digit PIN does not change. ## Hand off to a human Give the intended owner the `claim_url` and `claim_pin` together. The human must: 1. Sign in to Tilde. 2. Select the organization that should own the temporary workspace. 3. Open the claim URL. 4. Enter the six-digit PIN on Tilde's claim page. 5. Wait for the page to confirm the transfer. Five incorrect PIN attempts expire the current claim link. Generate a fresh link with the temporary API key if that happens. Claiming transfers the temporary team and supported resources into the human's selected organization. Tilde revokes the temporary API key after a successful claim. Reconnect with a human bearer token, a human-owned API key, or a new team-scoped agent API key; call `tilde_whoami` again and update any organization-qualified URLs. ## Discovery and API reference * OpenAPI: `https://trytilde.ai/openapi.json` * Agent context: `https://trytilde.ai/llms.txt` * Documentation: `https://trytilde.ai/docs` * OAuth protected-resource metadata: `https://trytilde.ai/.well-known/oauth-protected-resource` * OAuth authorization-server metadata: `https://trytilde.ai/.well-known/oauth-authorization-server` * AI Catalog: `https://trytilde.ai/.well-known/ai-catalog.json` * MCP server card: `https://api.trytilde.ai/mcp/server-card` * Legacy MCP server-card discovery alias: `https://trytilde.ai/.well-known/mcp/server-card.json` Use a bearer token or human-owned API key for a human. Use a team-scoped agent API key for a deployed agent. An authorized installation agent can create and reconcile other agents without borrowing a human credential. # ChatKit Source: https://trytilde.ai/docs/chatkit Connect conversations and external events to your agent. Building chat directly into your own frontend? Follow [Frontend chat with your own authentication](/docs/guides/frontend-chat) to set up identities, an organization proxy token, and a same-origin streaming proxy. ChatKit connects an agent endpoint to the places where work begins. It stores sessions and messages, delivers each turn as a signed HTTPS request, and streams the agent's response back to the channel. There are three ways to trigger an agent run through ChatKit: 1. **Chat providers**: These are first-class integrations with third-party chat providers. 2. **Vercel AI SDK chat provider**: This managed provider exposes your agent through a Vercel AI SDK-compatible endpoint for custom clients. 3. **Signals**: These are events from third-party providers that Tilde delivers to your agent. Configure chat providers for conversations from Slack, GitHub, Linq, and other supported channels. Use signals when an external event should start or continue a session without first arriving as a chat message. [Connect Linq messaging](/docs/guides/linq) once to provision its ChatKit channel, tools, Signals, and Reverse Proxy together. ChatKit sessions, routines, and agents are either shared `team` resources or private `user_team` resources. A private resource remains in its execution team and has one owner. Private sessions may also include selected team users as conversation members: members can see the session, read its history, send messages, and receive its live events, while the owner and team, organization, or system administrators manage membership and session administration. Messages, attachments, events, tasks, replies, and turn queues inherit the session's audience. Agents, sessions, and routines also expose independent visibility and ownership modes. Visibility controls discovery, history, messaging, and the realtime audience. Ownership controls settings, membership, grants, and deletion. Private user/group grants are tenant-scoped, and ownership or administrator authority alone does not reveal a private conversation. Session membership remains the conversation-specific way to admit additional team users. Session members are Tilde authorization principals, not ChatKit delivery participants. Adding an agent, Slack channel, or other inbox participant determines where messages flow; adding a Tilde user as a session member determines who may open the private conversation. Removing a member revokes subsequent history and event access, and leaving the execution team invalidates the grant. Each ChatKit realtime WebSocket retains its authenticated effective user and current Identity groups. Team agent lifecycle changes are sent to every connected team member. Private agent and session events follow their current visibility grants and conversation membership. Authorization changes emit an `access.changed` invalidation so clients refresh their personalized workspace projection. Realtime events use a closed, client-facing union: `agent.*`, `session.*`, `participant.*`, `message.*`, `queue_item.*`, `turn.*`, `activity.*`, `task.*`, and `chat.error`. Streaming content arrives through sequenced `message.delta` events. Internal event-bus payloads and audience identifiers are never forwarded. Read state belongs to the user-session relationship. `PUT /api/v1/team/{team_id}/chatkit/workspace/sessions/{session_id}/read-state` accepts `{ "unread": false }` when a user opens a session or `{ "unread": true }` to mark it manually. Other users sharing the session keep independent state. Signal provider instances and rules may also be personal. A personal rule names the team where its agent action runs. Sessions created by that rule are `user_team` sessions for the same owner, preventing the rule from turning personal activity into a team-visible conversation. Signal providers and rules use the same two planes. Visibility controls discovery and delivery inspection; ownership controls configuration, target/session policy, grants, state-changing retries, and deletion. Deliveries and sessions inherit the rule and target authorization rather than defining independent grants. Build a customer-hosted integration with [custom ChatKit providers](/docs/custom-chatkit-providers). Definitions are reusable within a team, and each connection has independent credentials and configuration. ## Set up ChatKit Wrap your route with `chatKitEndpoint`. It verifies Tilde's signature and gives the handler the current session, new messages, provider metadata, and ChatKit client. ```bash theme={"system"} pnpm add @ai-sdk/openai ai @trytilde/sdk @trytilde/sdk-vercel-ai-node ``` ```typescript app/api/agent/route.ts theme={"system"} import { openai } from "@ai-sdk/openai"; import { chatKitEndpoint, convertToAiSdkMessages, createClient, } from "@trytilde/sdk-vercel-ai-node"; import { consumeStream, convertToModelMessages, streamText } from "ai"; export const POST = chatKitEndpoint({ client: createClient({ apiKey: process.env.TILDE_API_KEY!, orgId: process.env.TILDE_ORG_ID!, teamId: process.env.TILDE_TEAM_ID!, }), webhookSigningKey: process.env.TILDE_WEBHOOK_SIGNING_KEY!, responseMode: "agentLoop", async handler(request, context) { const history = await context.session.history(); const messages = await convertToAiSdkMessages({ messages: [...history.items, ...context.messages], chatkit: context.chatkit, }); const result = streamText({ abortSignal: request.signal, messages: await convertToModelMessages(messages), model: openai("gpt-5.5"), }); return result.toUIMessageStreamResponse({ consumeSseStream: consumeStream, originalMessages: messages, }); }, }); ``` Keep the API key and webhook signing key in server-side environment variables. Open Tilde, select your workspace, and go to **ChatKit** → **Agents**. Choose **Team** when every team member should discover the agent, or **Private** when discovery and lifecycle updates should be limited to its visibility grantees. Register the endpoint and copy the one-time API key and webhook signing key into your app's environment. For local development, enable **Local running endpoint** and run the app through a [Dev Tunnel](/docs/dev-tunnels). For production, enter the deployed HTTPS endpoint. Registration also creates a credentialless **Message agent** tool provider bound to this agent. Add its `message` and `wait_for_response` tools to any Tilde MCP server when another agent should invoke it. Go to **ChatKit** → **Configure Chat Providers** and choose where people will talk to the agent. Link the provider to your registered agent, then open [ChatKit workspace](https://api.trytilde.ai/chatkit-workspace) to start a test session. ### Choose how the endpoint responds With AI SDK 7, keep system context in the model call's `instructions` field. Conversation `messages` must not contain system messages; recalled memory remains explicitly untrusted context. `chatKitEndpoint` requires a top-level `responseMode`: * `agentLoop` streams returned assistant text as the visible reply, preserving the existing endpoint pattern. * `tool` treats returned assistant text as private reasoning. The agent must call `context.session.tools.sendMessage` (also available through `context.$provider.tools`) for visible replies. Tool mode binds the current session, participant, provider, channel, thread, repository, issue, and recipient routing on the server. The model supplies only message content and provider-action inputs. Slack and GitHub expose reactions and thread reads; Linq exposes reactions, thread reads, poll creation, poll-option updates, and voting; AgentMail exposes thread reads and email delivery fields including `to`, `cc`, `bcc`, subject, HTML, and reply-all. Pass the same session context to `context.session.createMCPClient({ serverId: process.env.TILDE_MCP_SERVER_ID! })` when the agent consumes tools through MCP. Session tools are added without asking the model for routing identifiers. In a private owner-workspace session, Tilde also derives the authenticated human's personal Memory and Wiki tools from the authorized session. The agent keeps its own identity, and unrelated personal connections are not exposed. For a shared agent whose MCP server enables speaker-bound personal-tool federation, use `context.mcp.connect({ serverId })`. ChatKit forwards an invocation-scoped capability for the verified speaker outside model input. Tilde resolves only that speaker's eligible personal accounts; an unmapped external speaker receives no personal tools. The capability, user ID, account IDs, and credentials are never copied into messages or room state. ChatKit assigns compact participant handles and emits durable `participant.joined` and `participant.left` events when a participant becomes visible to or leaves the conversation. Conversation snapshots expose them in `participant_events`, separate from `messages`, so clients can render session activity without adding synthetic chat messages. Tilde still includes the lifecycle context in agent history, and these changes do not start an agent turn. ### Confirm an outbound message After creating a message, read `GET /api/v1/team/{team_id}/chatkit/session/{session_id}/message/{message_id}/deliveries` with the same organization scope. It requires visibility of the message and its session. Each receipt identifies the channel, provider, status, optional provider message ID, last error, and delivery timestamp. `provider_status` reports `pending`, `delivered`, or `failed` when the adapter can query final delivery status, as with Telnyx WhatsApp. That result takes precedence over initial queue acceptance: a later carrier rejection returns `dead_letter` and its error. Without a queryable provider status, `delivered` means acceptance. Neither means the recipient read the message. Keep the original message ID for an uncertain send; only a confirmed provider rejection establishes that a new attempt is safe. ### Share a room with people and agents A ChatKit session can be a private or team room with a durable human and agent roster. Room owners can invite a canonical Tilde user, select an `admin` or `member` collaboration role, add visible agents, inspect pending invitations, revoke an invitation, and remove a participant. The invited user accepts or declines before receiving private room history. Room roles do not replace resource permissions. Session visibility controls messages, attachments, replay, and live events. Session ownership controls invitations and roster administration. Removing a participant stops future delivery and speaker-bound personal-tool federation. `client.chatkit.rooms` exposes the typed roster and invitation contract. `runBoundedRoomGroup` deduplicates agents, caps participants and rounds, and stops when a round makes no progress. OpenBot currently keeps the owner room UI dormant until canonical human identity discovery can replace raw user identifiers; the underlying API and SDK contract are available. ### Keep substantial work durable Owner-only WhatsApp and Linq channels can opt into private conversations with `external_participant_policy: { join: "linked_only", agent_invocation: "linked_only", personal_tools: "linked_participants", session_scope: "personal" }` in their provider configuration. The sender must have a verified identity link routed to that channel and current team membership. Messages retain the verified human actor and the original channel's reply target. Existing shared conversations stay separate; a subsequent real inbound message starts or reuses the owner's private conversation. Other channels retain the default `session_scope: "team"` behavior. Goals, tasks, background jobs, routines, and AgentRuns let an agent continue substantial work without keeping correctness in one process. * A **goal** records the outcome for one agent and session. A **task** records an independently deliverable piece of that goal, including dependencies and progress. * A **background job** delegates one bounded objective to an explicit child agent. Jobs persist an optional `model_id`, hard duration/token/cost budgets, child session, transcript message IDs, artifacts, and terminal result. * An **AgentRun** persists the model-loop objective, generation-fenced lease, steps, token/cost totals, loop counters, wake state, and tool-effect receipts. * A **routine** stores recurring intent and its schedule. Prefer an event trigger when the same work can start from a Signal. Use `client.chatkit.work({ agentId, sessionId })` for goals, tasks, and jobs; `client.chatkit.routines(agentId)` for recurring work; and `client.chatkit.runs` for a durable host. Job actions are `steer`, `stop`, `resume`, and `collect-result`. Only the bound agent can mutate its work. Authorized owners can inspect and control the corresponding conversation work. Tilde supplies child job ID, generation, model, and budget in the signed request’s typed `execution` context. Hidden continuations carry the run ID, worker ID, generation, and hidden flag there. A continuation for a bound job also carries that job's context in `execution.job`, preserving its selected model and budget. Agent hosts must not accept caller-provided model, budget, run, or worker headers as authority. Bind a delegated model loop to its job by passing `job: { id: job.jobId, generation: job.generation }` to `client.chatkit.runs.create`. Use the direct `agent_job` execution context or the nested job context of an `agent_run` continuation. Tilde validates the child agent, session lineage, and current job generation, then creates or returns the one Run bound to that generation. Do not reuse an arbitrary active Run from the same session. `chatKitAgentRunIdempotencyKey(triggerId, context.execution)` still supplies retry identity; the typed binding supplies job authority. Ordinary human runs omit `job`. Once bound, an HTTP turn finishing does not complete the job. An active, waiting, paused, or stalled Run keeps the job running. The worker polls the same durable Run without redispatching the accepted HTTP invocation. A completed Run completes the job; a failed or canceled Run reports failure. Only that terminal result produces the parent's completion wake. Hosts without a bound Run retain the HTTP-terminal contract. Pass `expectedGeneration: run.generation` when recording a step with `client.chatkit.runs.appendStep`; the SDK sends `expected_generation`. Bound runs require that fence in addition to the current worker lease, so accounting from an older generation cannot land after steering. It remains optional for legacy unbound runs. Steering a bound job queues the instruction until the Run reaches an idle continuation boundary with no active lease or unresolved tool effect. The next continuation waits for pending steering. Tilde updates the existing Run and acknowledges the command atomically. Stopping the job cancels its bound Run; resuming creates a fresh job generation and a separate Run binding. A hidden continuation records its completed step before requesting a run transition. Tilde atomically acknowledges the matching planned continuation and applies that transition only for the current generation and unexpired worker lease, with a durable step recorded after the continuation started. Owner control cannot acknowledge a pending continuation, and an uncertain receipt still requires reconciliation or cancellation. ### Compact model context without rewriting history Context compaction changes model input, not ChatKit history. An agent reports `started`, `ended`, or `failed` lifecycle events to `/chatkit/sessions/{session_id}/compaction-events`. A successful checkpoint stores the exact summary, agent, transcript boundary, compacted and retained message IDs, and token counts. Load `/chatkit/sessions/{session_id}/messages/from-last-compaction?agent_id=...` to receive the latest successful checkpoint separately from retained and newer messages. In `@trytilde/sdk-vercel-ai-node`, `createChatKitCompactionController` supplies a bounded `prepareStep` loop and `composeChatKitCompactionPrepareStep` preserves provider preparation before applying compaction. Human-created private workspace sessions belong to the authenticated human, including when a deployment service owns the selected agent. Tilde binds the workspace participant to that human for personal tool access. Delegated child sessions inherit the parent session's ownership. ### Test your agent in ChatKit workspace Use [ChatKit workspace](https://api.trytilde.ai/chatkit-workspace) to invoke your agent directly and test conversations. Select the correct workspace and agent, then start a session and send a message. When creating a private session, the creator becomes its owner automatically. The create request may include additional team user IDs, and the session membership endpoints can list, add, or remove non-owner members afterward. Members receive the same live message and agent-turn stream for that session; they do not gain permission to change ownership or manage other members. ChatKit workspace requires the **Vercel AI Endpoint** ChatKit provider to be enabled for your agent. ### Approve agent-requested capability changes An agent may create a durable self-extension proposal when it needs a connector, MCP server, skill registry, custom tool, agent bundle, memory bank, or wiki that it cannot already use. Tilde validates the requested category, rejects secret-shaped fields, and authors the permission, credential, cost, audience, egress, security, and undo preview. The active conversation renders that proposal as a secure **Yes** or **No** Human Approval card. The decision is bound to the proposal ID, immutable proposal hash, proposal generation, authenticated human principal, requesting agent, and originating session. A typed button decision is required; free-text confirmation in chat does not approve a proposal. Only the requesting agent's human owner, a human team administrator, or a system administrator can decide the proposal. The requesting human cannot approve their own request, and an agent credential cannot approve, reject, cancel, roll back, or claim one-time outputs. **Yes** atomically completes the linked Human Approval and queues leased execution. **No** atomically cancels the approval and records proposal rejection. Credential values, credential references, approval tokens, OAuth state, and generated signing keys are never included in model-visible proposal text. If execution needs provider setup, the server returns a secret-free setup-item reference only after approval. The approving human continues through the normal server-authored credential or OAuth card. The original agent can then resume its task from the durable decision and proposal status. Execution records whether each resource was created by the proposal or reused. Rollback removes only proposal-created receipts. One-time generated values are encrypted and can be consumed once through the human-only outputs endpoint. ### Search conversations Use consolidated ChatKit search to find session titles, agents participating in sessions, and message content that you can view in a workspace. Results include the session context needed to open the matching conversation. ```bash theme={"system"} curl --get \ --header "Authorization: Bearer $TILDE_API_KEY" \ --data-urlencode "q=deployment rollback" \ --data-urlencode "page_size=25" \ "https://api.trytilde.ai/api/v1/team/$TILDE_TEAM_ID/chatkit/workspace/search" ``` Each result has a `kind` of `session_title`, `agent`, or `message`. Message results include the canonical ChatKit message. Use the opaque `next_page_token` to continue in relevance order. To search messages inside one conversation, add its `session_id`. Session-scoped search returns message results only and returns `404` if the session is not visible to you or does not belong to the selected workspace. ```bash theme={"system"} curl --get \ --header "Authorization: Bearer $TILDE_API_KEY" \ --data-urlencode "q=customer reference" \ --data-urlencode "session_id=$TILDE_SESSION_ID" \ "https://api.trytilde.ai/api/v1/team/$TILDE_TEAM_ID/chatkit/workspace/search" ``` Search uses case-insensitive full-text terms. It does not provide fuzzy, typo-tolerant, or substring matching. ### Audit coding-agent sessions Connect Codex, Claude Code, Cursor, OpenCode, or Gemini CLI with `openbot plugin` to record coding sessions in ChatKit while installing the Tilde MCP servers and managed skills you select. ```bash theme={"system"} openbot plugin --cli codex --agent-id "$TILDE_CHATKIT_AGENT_ID" openbot plugin --cli claude --agent-id "$TILDE_CHATKIT_AGENT_ID" openbot plugin --cli cursor --agent-id "$TILDE_CHATKIT_AGENT_ID" openbot plugin --cli opencode --agent-id "$TILDE_CHATKIT_AGENT_ID" openbot plugin --cli gemini --agent-id "$TILDE_CHATKIT_AGENT_ID" ``` The setup command installs the harness's native lifecycle hooks. Codex receives a Tilde plugin because Codex hooks are plugin-owned. OpenCode receives a fail-open global plugin. Claude Code, Cursor, and Gemini CLI use their user hook settings. Authentication stays in the existing Tilde plugin token store, while the hook routing file contains only the API URL, team ID, and agent ID. Each coding-agent session maps to one tenant-scoped ChatKit session. User prompts and final responses become ordinary searchable messages. Tool start, completion, and failure hooks become canonical tool executions with stable source, session, and call correlation. Tilde MCP tools and process-local tools share the same audit model. Canonical tool executions retain their input, output, and errors for audit. Choose an agent with the correct visibility grants and do not pass secrets in prompts or tool arguments. Browser views still apply the agent's ChatKit observability policy; storage does not discard details merely because a view hides them. Use the normal ChatKit search endpoint to find coding-session prompts and responses across sessions. A repeated hook delivery reuses the original lookup-key session and tool execution identity instead of creating a second conversation. ### Provider-specific message metadata Supported chat providers add validated metadata to the endpoint context. Use the provider-specific property inside your `chatKitEndpoint` handler. GitHub messages expose repository, issue, pull request, comment, and event metadata through `context.github`. ```typescript app/api/code-review/route.ts theme={"system"} import { chatKitEndpoint, createClient, } from "@trytilde/sdk-vercel-ai-node"; export const POST = chatKitEndpoint({ client: createClient({ apiKey: process.env.TILDE_API_KEY!, orgId: process.env.TILDE_ORG_ID!, teamId: process.env.TILDE_TEAM_ID!, }), webhookSigningKey: process.env.TILDE_WEBHOOK_SIGNING_KEY!, responseMode: "agentLoop", async handler(_request, context) { console.log({ event: context.github?.event, owner: context.github?.owner, repo: context.github?.repo, pullNumber: context.github?.pull_number, issueNumber: context.github?.issue_number, }); // ...rest of your agent code. }, }); ``` Slack messages expose the workspace, channel, thread, message, and sender metadata through `context.slack`. ```typescript app/api/slack-agent/route.ts theme={"system"} import { chatKitEndpoint, createClient, } from "@trytilde/sdk-vercel-ai-node"; export const POST = chatKitEndpoint({ client: createClient({ apiKey: process.env.TILDE_API_KEY!, orgId: process.env.TILDE_ORG_ID!, teamId: process.env.TILDE_TEAM_ID!, }), webhookSigningKey: process.env.TILDE_WEBHOOK_SIGNING_KEY!, responseMode: "agentLoop", async handler(_request, context) { console.log({ teamId: context.slack?.team_id, channelId: context.slack?.channel_id, threadTimestamp: context.slack?.thread_ts, userId: context.slack?.user, }); // ...rest of your agent code. }, }); ``` ## Work with session context `context.messages` contains the new input for the current turn. Load `context.session.history()` when the model needs the earlier conversation, then convert both collections together. ```typescript theme={"system"} const history = await context.session.history(); const messages = await convertToAiSdkMessages({ messages: [...history.items, ...context.messages], chatkit: context.chatkit, }); ``` The context also includes `sessionId`, team and organization IDs, the invoking user when known, and typed metadata for supported providers such as `context.slack` and `context.github`. For agent-to-agent delegation, `context.body.session.parentAgentId` identifies the authenticated agent that opened the child session. Direct conversations omit it. A specialist that operates caller-owned runtime state—such as a browser display—can use this server-authored ID to continue the caller's state without accepting a routing identity from model input or client parameters. `context.agent` identifies the agent receiving the current turn. It includes the canonical `id`, `displayName`, `providerId`, `status`, optional `principalUserId`, optional authenticated `avatar.url`, and `createdAt` / `updatedAt` timestamps from Tilde. Use this context instead of duplicating an agent name or avatar in application configuration. ```typescript theme={"system"} const receivingAgent = { id: context.agent?.id, name: context.agent?.displayName, avatarUrl: context.agent?.avatar?.url, }; ``` The avatar URL is a Tilde API path and requires the same server-side Tilde authentication as other agent resources. The `agent` field is optional on the wire so an updated SDK remains compatible with requests from an older Tilde deployment. ## Handle unprocessed content `convertToAiSdkMessages` automatically converts standard text and reasoning parts. It also caches transformed message parts for later model requests, improving prompt caching and agent performance. Use `onUnprocessed` for content that needs application-specific handling before it can be sent to a model. * `fileUpload` receives each unprocessed file part and its parent message. * `firecrawl` maps page-monitoring and completed-check signals to typed message converters. * `github` maps GitHub issue, pull request, and CI signal types to typed message converters. * `sentry` maps a signal type, such as `sentry.issue.created`, to a typed message converter. * Return an AI SDK message or part to include it. Return `null` to omit it. * Handlers can be asynchronous. If a handler throws, message conversion fails. ChatKit invokes `onUnprocessed` once for each unprocessed message, then caches the result. Subsequent conversions reuse the cached value instead of invoking the handler again. Use `createChatKitAttachmentFilePartHandler` to download ChatKit attachments with Tilde authentication and convert them into model-safe AI SDK file parts. ```typescript app/api/agent/route.ts theme={"system"} import type { Client } from "@trytilde/sdk"; import { type ChatKitEndpointContext, convertToAiSdkMessages, createChatKitAttachmentFilePartHandler, } from "@trytilde/sdk-vercel-ai-node"; async function convertTurn( client: Client, context: ChatKitEndpointContext, ) { const history = await context.session.history(); return convertToAiSdkMessages({ messages: [...history.items, ...context.messages], chatkit: context.chatkit, onUnprocessed: { fileUpload: createChatKitAttachmentFilePartHandler(client, context), }, }); } ``` Supported media is downloaded and passed to the model as an inline file. Unsupported stored attachments become a text part containing the file name, media type, and download URL. Add a handler for each GitHub event your agent should receive. The signal type narrows the webhook payload automatically. ```typescript app/api/github-agent/route.ts theme={"system"} import { type ChatKitEndpointContext, convertToAiSdkMessages, type GitHubSignalByType, } from "@trytilde/sdk-vercel-ai-node"; import type { UIMessage } from "ai"; type PullRequestOpened = GitHubSignalByType["github.pull_request.opened"]; function pullRequestOpenedMessage( signal: PullRequestOpened, ): UIMessage { const { repository, pull_request } = signal.data; return { id: signal.id, role: "user", parts: [{ type: "text", text: `Review ${repository.full_name}#${pull_request.number}: ${pull_request.title}`, }], }; } async function messagesForGitHubTurn( context: ChatKitEndpointContext, ) { const history = await context.session.history(); return convertToAiSdkMessages({ messages: [...history.items, ...context.messages], chatkit: context.chatkit, onUnprocessed: { github: { "github.pull_request.opened": pullRequestOpenedMessage, }, }, }); } ``` GitHub chat provider messages still use the typed `context.github` metadata described above. Handle Firecrawl Monitor events with typed access to the monitor, check, page, result, and webhook metadata. ```typescript app/api/web-monitor/route.ts theme={"system"} import { type ChatKitEndpointContext, convertToAiSdkMessages, type FirecrawlSignalByType, } from "@trytilde/sdk-vercel-ai-node"; import type { UIMessage } from "ai"; type PageChanged = FirecrawlSignalByType["firecrawl.monitor.page.changed"]; function pageChangedMessage(signal: PageChanged): UIMessage { const { monitor, page } = signal.data; return { id: signal.id, role: "user", parts: [{ type: "text", text: `Review changes to ${page.url} from monitor ${monitor.id}.`, }], }; } async function messagesForFirecrawlTurn( context: ChatKitEndpointContext, ) { const history = await context.session.history(); return convertToAiSdkMessages({ messages: [...history.items, ...context.messages], chatkit: context.chatkit, onUnprocessed: { firecrawl: { "firecrawl.monitor.page.changed": pageChangedMessage, }, }, }); } ``` Firecrawl also exposes `same`, `new`, `removed`, and `error` page events, plus `firecrawl.monitor.check.completed` for the completed check summary. Handle Sentry issue events through the matching typed signal branch. ```typescript app/api/sentry-agent/route.ts theme={"system"} import { type ChatKitEndpointContext, convertToAiSdkMessages, type SentrySignalByType, } from "@trytilde/sdk-vercel-ai-node"; import type { UIMessage } from "ai"; type IssueCreated = SentrySignalByType["sentry.issue.created"]; function issueCreatedMessage(signal: IssueCreated): UIMessage { const { issue } = signal.data.data; return { id: signal.id, role: "user", parts: [{ type: "text", text: `Investigate ${issue.shortId ?? issue.id}: ${issue.title}`, }], }; } async function messagesForSentryTurn( context: ChatKitEndpointContext, ) { const history = await context.session.history(); return convertToAiSdkMessages({ messages: [...history.items, ...context.messages], chatkit: context.chatkit, onUnprocessed: { sentry: { "sentry.issue.created": issueCreatedMessage, }, }, }); } ``` The Signals section below shows how typed handlers fit into the complete event workflow. ## Choose how new turns are handled Each chat provider can control what happens when another message arrives while the agent is still working. When a message comes from the agent's generated MCP provider, ChatKit uses the policy configured on the target agent. | Policy | Behavior | | ----------------- | ------------------------------------------------------------------ | | **Queue** | Finish the current response, then process new messages in order. | | **Interrupt** | Stop the current response and immediately send the newest message. | | **Queue & batch** | Keep one pending turn and combine further messages into it. | ## Let agents invoke other agents through MCP Every registered agent has a generated **Message agent** tool provider. Add that provider to an existing MCP server just like any other credentialless provider. Its routing fields are fixed to the target agent, so callers only supply the message and, optionally, a ChatKit session ID. * `message` accepts Vercel AI SDK-compatible UI message parts, persists the inbound ChatKit message, and immediately returns a ticket and session ID. * `wait_for_response` accepts that ticket, subscribes to the live ChatKit session, streams response deltas through MCP progress notifications (or logging notifications when the caller did not supply a progress token), and returns the final canonical ChatKit message. * Reuse the returned session ID to continue the same child-agent conversation. Omit it to create a new session. * Queue status notifications include the target agent's concurrency policy and whether multiple messages were batched into the turn. The former pairwise internal-agent chat provider is no longer used. Agent-to-agent routing is now composed through ordinary MCP servers, so one generated provider can be reused by any authorized parent agent. ## Trigger work from events via Signals Signals turn supported external events into ChatKit messages. A rule selects an event type, maps it to an agent, and determines whether related events reuse the same session. Use a stable session key when repeated events belong to the same body of work. For example, route every update for one Sentry issue into the same remediation session so the agent can continue from its existing history. Map typed signal messages while converting ChatKit history. This example turns a Sentry `issue.created` signal into the user message sent to the model. ```typescript app/api/sentry-remediation/route.ts theme={"system"} import { chatKitEndpoint, convertToAiSdkMessages, createClient, type SentrySignalByType, } from "@trytilde/sdk-vercel-ai-node"; import type { UIMessage } from "ai"; type IssueCreatedSignal = SentrySignalByType["sentry.issue.created"]; function sentryIssueCreatedMessage(signal: IssueCreatedSignal): UIMessage { const { issue } = signal.data.data; return { id: signal.id, role: "user", parts: [ { type: "text", text: `Investigate Sentry issue ${issue.shortId ?? issue.id}: ${issue.title}`, }, ], }; } export const POST = chatKitEndpoint({ client: createClient({ apiKey: process.env.TILDE_API_KEY!, orgId: process.env.TILDE_ORG_ID!, teamId: process.env.TILDE_TEAM_ID!, }), webhookSigningKey: process.env.TILDE_WEBHOOK_SIGNING_KEY!, responseMode: "agentLoop", async handler(_request, context) { const history = await context.session.history(); const messages = await convertToAiSdkMessages({ messages: [...history.items, ...context.messages], chatkit: context.chatkit, onUnprocessed: { sentry: { "sentry.issue.created": sentryIssueCreatedMessage, }, }, }); // ...rest of your agent code. }, }); ``` ## ChatKit and memory ChatKit preserves the messages inside a session. [Memory](/docs/memory) stores selected knowledge that should be available across sessions, channels, or agents. Use both when an agent needs conversational continuity and longer-lived organizational context. ## Configure realtime voice Voice settings belong to your Tilde agent. In agent registration, select a voice profile and its models, voice, and maximum conversation duration. You can change these settings in the agent editor later. * **Text agent with speech**: Tilde transcribes incoming audio, invokes your normal `chatKitEndpoint` callback, and speaks its streamed text response. * **Telnyx Conversation Relay**: Telnyx handles recognition and speech synthesis for incoming phone calls. Tilde receives caller text, invokes your normal callback, and streams its response text to Telnyx. This profile is phone-only. * **OpenAI Realtime**: the realtime model generates spoken responses directly. Tilde records the final transcripts without invoking your text endpoint again. Your text callback receives `context.audio` for transcribed speech turns and `context.telnyx` for Telnyx calls. Provider facts are supplied in the signed request. A subsequent typed message does not become a speech turn merely because its session previously contained a call. Each call creates a normal ChatKit session. Browser media admission is one-time, expires after five minutes, and remains subject to current session membership. Call duration is limited by the configured maximum. Call recordings are not retained by this initial realtime implementation. For a manual test, use the SDK repository's `examples/realtime-voice` example. It registers three agents. Its microphone page supports the two OpenAI modes; a dedicated relay endpoint handles phone calls. To receive calls, configure a **Telnyx Voice** chat provider with an existing encrypted Telnyx Voice credential, Voice API application, phone number, and default agent. This creates a real ChatKit channel that owns the caller's participant route. Choose **self-managed webhook setup** to copy Tilde's returned webhook URL into Telnyx yourself. Choose **managed webhook setup** to let Tilde update the existing application's webhook URL using your credential. Managed setup does not provision or fund a Telnyx account, purchase a number, or assign numbers to applications. Use a dedicated test application for the manual example. The Tilde API must be publicly reachable through HTTPS and WSS. Hookdeck webhook replay alone cannot carry live bidirectional calls. For relay, select `telnyx_relay`, transcription model `deepgram/nova-3`, voice `Telnyx.Ultra.Callie`, language `en-US`, and interruption enabled. The Telnyx route uses its own credential; relay does not require an OpenAI speech key. Your callback continues to use its own text model and tools. The SDK example accepts `TELNYX_AGENT_MODE=telnyx_relay` and keeps the browser demos available. Partial relay transcripts do not start agent turns. When speech interrupts a response, Tilde retains generated text and separately records the spoken prefix reported by the carrier. The SDK annotates both text and UI history so the next turn can distinguish generated words from that reported prefix. Caller ID does not authorize access to a Tilde human's personal tools. The [Telnyx Conversation Relay guide](https://developers.telnyx.com/docs/voice/programmable-voice/conversation-relay) describes the text WebSocket protocol used between Telnyx and Tilde. The initial browser implementation streams audio through the Rust API. Direct browser-to-provider WebRTC and direct SIP routing are separate transport options and are not implied by the OpenAI Realtime profile. Native Realtime uses its configured instructions and does not inherit endpoint tools. Browser voice identifies its caller but does not yet establish personal-tool federation. ## Change resources through native tools Agents use native Tilde API/MCP operations under their existing permissions. The capability proposal API has been retired. Chain dependent operations using returned resource IDs, reconcile partial failures before retrying, and read back the resulting resource. Do not widen permissions or switch credentials after an authorization failure. Before enabling a connector, read the managed [enable-connections skill](https://docs.trytilde.ai/llms/connections.md). Discover existing user and agent access and verify the correct account first. Choose personal/user or bot ownership explicitly; when unclear, ask whether other bots should be able to use the account. Native brokering returns a `connector_setup_required` descriptor for the pending resource. API clients render an enable-provider event outside message bubbles and open secure configuration modals. In external channels, invoke sendMessage with the server-returned hosted setup URL. Credentials stay in native secure setup operations, outside chat and persisted client workflow snapshots. ## Recover missing conversation context Session-scoped MCP connections provide `chatkit_search_history`. The query searches the current conversation by default. Set `include_related_sessions` to search other conversations that the authenticated agent actively participates in with the current session's verified human owner. Ordinary search permissions also apply. Models cannot supply a different agent, tenant or user identity to this tool. Follow `next_page_token`, even after an empty filtered page. # Set up ChatGPT Source: https://trytilde.ai/docs/connect-your-agent/chatgpt Connect ChatGPT to the global Tilde MCP server with secure Tilde login. [← All clients](/docs/connect-your-agent) In ChatGPT, go to **Settings → Apps → Advanced settings** and turn on **Developer Mode**. This requires ChatGPT Plus, Pro, Business, Enterprise, or Edu. Click **Create app** and paste the Tilde MCP server URL. ```text MCP URL theme={"system"} https://api.trytilde.ai/mcp ``` A browser window opens automatically. Sign in to authorize ChatGPT to access your Tilde account. In each new chat, click **+**, click **More**, then select **Tilde** to enable its tools for that conversation. # Set up Claude Code Source: https://trytilde.ai/docs/connect-your-agent/claude-code Connect Claude Code to the global Tilde MCP server with secure Tilde login. [← All clients](/docs/connect-your-agent) Run this command to add Tilde as a user-scoped Streamable HTTP MCP server. ```bash Terminal theme={"system"} claude mcp add --scope user --transport http tilde https://api.trytilde.ai/mcp ``` Open Claude Code and type `/mcp`. Select **Tilde**, then follow the browser login flow. Confirm that Tilde appears as connected in the `/mcp` server list. # Set up Claude Desktop Source: https://trytilde.ai/docs/connect-your-agent/claude-desktop Connect Claude Desktop to the global Tilde MCP server with secure Tilde login. [← All clients](/docs/connect-your-agent) In Claude Desktop, go to **Settings**, then click **Connectors**. Click **Add custom connector** and paste the Tilde MCP server URL. ```text MCP URL theme={"system"} https://api.trytilde.ai/mcp ``` A browser window opens automatically. Sign in to authorize Claude Desktop to access your Tilde account. Tilde tools are now available in Claude Desktop. # Set up Cline Source: https://trytilde.ai/docs/connect-your-agent/cline Connect Cline to the global Tilde MCP server with secure Tilde login. [← All clients](/docs/connect-your-agent) In VS Code with Cline installed, click the **MCP Servers** icon in the Cline navigation bar. Click **Configure**, then click **Configure MCP Servers**. Add this configuration: ```json MCP Settings theme={"system"} { "mcpServers": { "tilde": { "url": "https://api.trytilde.ai/mcp", "type": "streamableHttp", "disabled": false } } } ``` Save the configuration. Cline opens a browser window where you can authorize access to your Tilde account. # Set up Codex Source: https://trytilde.ai/docs/connect-your-agent/codex Connect Codex to the global Tilde MCP server with secure Tilde login. [← All clients](/docs/connect-your-agent) Run this command to add the Tilde MCP server to Codex. ```bash Terminal theme={"system"} codex mcp add tilde --url https://api.trytilde.ai/mcp ``` Run the login command. Codex opens a browser window where you can authorize access to Tilde. ```bash Terminal theme={"system"} codex mcp login tilde ``` Confirm that Tilde appears as a registered MCP server. ```bash Terminal theme={"system"} codex mcp list ``` # Set up Cursor Source: https://trytilde.ai/docs/connect-your-agent/cursor Connect Cursor to the global Tilde MCP server with secure Tilde login. [← All clients](/docs/connect-your-agent) [Install Tilde in Cursor](https://cursor.com/en/install-mcp?name=tilde\&config=eyJ1cmwiOiJodHRwczovL2FwaS50cnl0aWxkZS5haS9tY3AifQ%3D%3D), then authorize access in your browser. Open `.cursor/mcp.json` in your project or `~/.cursor/mcp.json` for global configuration. Add this entry: ```json mcp.json theme={"system"} { "mcpServers": { "tilde": { "url": "https://api.trytilde.ai/mcp" } } } ``` Restart Cursor, then click **Connect** next to Tilde in MCP Tools settings. Sign in when the browser window opens. # Connect your coding agent Source: https://trytilde.ai/docs/connect-your-agent/index Connect a supported coding agent or MCP client to Tilde. Connect the client where your agent runs to the global Tilde MCP server. ## Choose your coding agent Select where your agent runs, then follow the setup instructions for that client. ### OpenClaw ### Claude ### Codex + ChatGPT ### MCP The global endpoint infers your organization from your Tilde login. Tools that act on a team require a `team_id`. # Use the MCP URL Source: https://trytilde.ai/docs/connect-your-agent/mcp-url Connect any compatible client to the global Tilde MCP server. [← All clients](/docs/connect-your-agent) Use this Streamable HTTP endpoint with any compatible MCP client. ```text MCP URL theme={"system"} https://api.trytilde.ai/mcp ``` Do not add custom authentication headers. Your client should detect OAuth and open hosted Tilde login when it connects. Use this general configuration when your client accepts an `mcpServers` object: ```json MCP config theme={"system"} { "mcpServers": { "tilde": { "url": "https://api.trytilde.ai/mcp" } } } ``` # Set up n8n Source: https://trytilde.ai/docs/connect-your-agent/n8n Connect n8n to the global Tilde MCP server. [← All clients](/docs/connect-your-agent) Add an **MCP Client** node, or an **MCP Client Tool** sub-node for an AI agent chain. Set the connection type to **HTTP Streamable**. Paste the global Tilde MCP server URL. ```text MCP URL theme={"system"} https://api.trytilde.ai/mcp ``` Use hosted Tilde login if your n8n MCP client supports browser authorization. Click **Connect**. Tilde tools are now available in your workflow. # Set up Notion Source: https://trytilde.ai/docs/connect-your-agent/notion Connect a Notion custom agent to the global Tilde MCP server. [← All clients](/docs/connect-your-agent) In Notion, open the AI agent builder and click **Create Blank**. Click **Add Connection**, then select **Custom MCP**. Enter the global Tilde MCP server URL. ```text MCP URL theme={"system"} https://api.trytilde.ai/mcp ``` Name the connection `Tilde`. Notion detects OAuth and opens a browser window. Sign in to authorize access to your Tilde account. Tilde tools are now available in your Notion agent. # Set up OpenAI Agent Builder Source: https://trytilde.ai/docs/connect-your-agent/openai-agent-builder Connect OpenAI Agent Builder to the global Tilde MCP server. [← All clients](/docs/connect-your-agent) [Open Agent Builder](https://platform.openai.com/agent-builder) and create an agent. In your agent, click **MCP** in the sidebar, then click **+ Server**. Paste the global Tilde MCP server URL. ```text MCP URL theme={"system"} https://api.trytilde.ai/mcp ``` Use hosted Tilde login when Agent Builder asks you to authorize. Click **Connect**. Tilde tools are now available in your agent. # Set up OpenClaw Source: https://trytilde.ai/docs/connect-your-agent/openclaw Connect OpenClaw to the global Tilde MCP server with secure Tilde login. [← All clients](/docs/connect-your-agent) Copy this prompt and paste it into OpenClaw. ```text Prompt theme={"system"} Add a new MCP server called "tilde" with transport type HTTP. Use the URL https://api.trytilde.ai/mcp. Do not add any authentication headers. OAuth will be used automatically. ``` OpenClaw detects OAuth and opens a browser window. Sign in to authorize access to your Tilde account. Tilde tools are now available in OpenClaw. # Set up VS Code Source: https://trytilde.ai/docs/connect-your-agent/vscode Connect GitHub Copilot in VS Code to the global Tilde MCP server. [← All clients](/docs/connect-your-agent) [Install Tilde in VS Code](vscode:mcp/install?%7B%22name%22%3A%22tilde%22%2C%22type%22%3A%22http%22%2C%22url%22%3A%22https%3A%2F%2Fapi.trytilde.ai%2Fmcp%22%7D). This requires VS Code 1.99 or later with GitHub Copilot. Open or create `.vscode/mcp.json` in your project and add this configuration: ```json mcp.json theme={"system"} { "servers": { "tilde": { "type": "http", "url": "https://api.trytilde.ai/mcp" } } } ``` Click **Start** in the CodeLens above the server entry, or open a GitHub Copilot chat. VS Code detects OAuth and asks you to sign in. # Set up Windsurf Source: https://trytilde.ai/docs/connect-your-agent/windsurf Connect Windsurf to the global Tilde MCP server with secure Tilde login. [← All clients](/docs/connect-your-agent) Open `~/.codeium/windsurf/mcp_config.json`, or go to **Windsurf → Settings → MCP Configuration**. Add this configuration: ```json mcp_config.json theme={"system"} { "mcpServers": { "tilde": { "serverUrl": "https://api.trytilde.ai/mcp" } } } ``` Restart Windsurf, then click **Authorize** next to Tilde. Sign in when the browser window opens. Tilde tools are now available in Cascade. # Custom ChatKit providers Source: https://trytilde.ai/docs/custom-chatkit-providers Host your own chat integration with the TypeScript SDK. A custom ChatKit provider connects your platform to Tilde's canonical sessions, agent execution, and durable delivery. You host the provider backend. Tilde stores a reusable, team-scoped definition and creates an independent connection for each configured account. Your backend verifies external webhook signatures, interprets platform threads and identities, and converts messages. Tilde owns authorization, conversation participants, tool-execution records, and delivery retries. Provider runtime credentials cannot act as Tilde users. ## Register and connect 1. Open **ChatKit → Configure providers** and register the backend's HTTPS discovery URL. Registration creates a pending definition and returns its signing key once. 2. Configure that key and the returned definition ID in your backend, then refresh discovery. A failed refresh preserves the last valid manifest and records diagnostics. Changes incompatible with existing connections require a new definition. 3. Choose the provider in the generic setup catalog. Configure the connection's default agent, credentials, and platform settings. The backend can request forms, authorization redirects, or setup instructions. Use **Inspect connections** to configure a pending imported connection or resume interrupted setup. 4. Send external webhooks directly to your backend. Verify the platform's raw request before submitting normalized events to Tilde. You can also manage definitions through `client.chatkit.customProviders`: ```typescript theme={"system"} const registration = await client.chatkit.customProviders.create({ displayName: "My chat platform", discoveryUrl: "https://provider.example/provider", }); // Store registration.signingKey in your backend's secret manager. // Configure registration.provider.id as the endpoint's definitionId. await client.chatkit.customProviders.refresh({ providerId: registration.provider.id, }); ``` Use `startConnection` and `resumeConnection` for SDK-driven setup. Their `nextAction` describes the next generic setup step. Responses may contain one-time secret outputs; keep those out of transcripts and application logs. ## Author a backend Import `defineChatKitProvider`, `chatKitProviderEndpoint`, and `createProviderRuntimeClient` from `@trytilde/sdk/chatkit-provider`. The endpoint uses standard `Request` and `Response` objects and does not require Vercel AI. Export its `GET` handler for discovery and `POST` handler for signed operations. Your definition declares configuration schemas, authentication methods, subscriptions, content capabilities, and session tools. Implement the matching setup, identity, messaging, and tool handlers. Declare only supported capabilities. The SDK validates manifests and verifies Tilde's operation signature before invoking your code. A signed operation binds the protocol version, request ID, definition, connection, and execution context. Configuration and managed credentials arrive only at authorized backend operations. For OAuth, verify the platform callback and redirect the browser to the supplied `input.return_url`. It carries Tilde's persisted setup binding; the dashboard resumes that setup as the signed-in user. Store connection runtime tokens securely; use `setup.credentialsUpdated` to handle rotation. Dispatch's `packages/sdk/examples/custom-chatkit` directory contains Linq and AgentMail adapters, a runnable Node host, and a custom streaming protocol. Linq covers line selection, subscriptions, reactions, thread reads, and polls. AgentMail covers inbox credentials, email threading, rich recipients, HTML, reply-all, and attachments. ## Ingest messages and identities Use a connection-scoped runtime client to ensure a conversation and ingest a normalized message. Event IDs, external identities, and conversation keys are scoped to the connection, so two accounts can safely reuse the same external IDs. Tilde durably accepts each event and rejects conflicting reuse of an ID. Polling and socket consumers use the same API as webhook handlers. The runtime client supports attachment uploads and downloads, external participant updates, history, agent address registration, and mention normalization. External addresses are delivery identities; adding one never grants Tilde-user access. Upload attachments before referencing their IDs in an inbound message. ## Session tools Declare contextual tools such as `addReaction`, `getThread`, or your platform's own actions. Discovery can narrow the declaration based on the current connection and participants. Tilde intersects the result with the authenticated agent's actual turn and target authorization. Agents discover bound tools with `client.chatkit.sessionTools({ sessionId })`. The Vercel AI adapter exposes `context.session.tools` and a standalone `sessionProviderTools` helper. Session-scoped MCP exposes provider actions with the `chatkit_provider__` prefix. Common canonical names such as `sendMessage` cannot be shadowed. Keep the model's tool-call ID stable across retries. Tilde binds the agent, session, target, trigger, connection, and execution ID outside model arguments. Each mutation must support reconciliation. Return `applied` with its result, `absent` only when a retry is safe, or `uncertain` when the outcome is unknown. A missing local receipt alone does not prove that the platform operation failed. ## Rich delivery `sendMessage` stores one canonical message and durable delivery intent. Providers prepare private delivery options and deliver the persisted output. Automatic replies and explicit sends use the same delivery worker. To/CC/BCC, subject, HTML, reply-all, and provider-specific options do not need to be reconstructed from visible text. Tilde encrypts the private delivery envelope. BCC stays out of shared transcripts, participant lists, realtime payloads, and ordinary execution records. The email reference supports `provider_options: { new_thread: true }` with explicit To recipients when starting a new email from an authorized session turn. Providers must also redact BCC from their own tool results and inbound extension data. Use the supplied delivery ID for platform idempotency or delivery markers. Reconciliation runs before retrying an uncertain send. Attachment URLs are refreshed for delivery attempts. Exhausted retries remain visible as dead letters. Use `client.chatkit.customProviders.listConnectionWork` to inspect ingestion and cleanup status without reading message payloads. After correcting a backend failure, use `retryConnectionWork` with the returned work ID. ## Client transports Custom client protocols can submit canonical turns, read history, and subscribe to `client.chatkit.streamSessionEvents`. Authenticate each caller with their own SDK client. Reconnect with the last event cursor and use history for a fresh snapshot. Tilde filters events by the current audience and periodically revalidates stream authorization. A provider runtime token is for external platform operations. It cannot impersonate a user or replace caller authentication for a streaming client. ## Lifecycle and portability Disabling a definition pauses its connections' runtime work and pending delivery. Re-enabling resumes them. Deleting a connection revokes its runtime credential, cancels pending delivery, and schedules external cleanup while retaining conversation history. A referenced definition cannot be deleted. Setup can provision an associated custom Tools backend through the existing Tools lifecycle. The connection owns its typed toolkit reference and cleans it up on deletion. Tools retain their own enablement settings; session tools do not require a separate toolkit instance. State exports include public definitions, connection configuration, and portable agent/toolkit references. Imports require discovery and credential rebinding before runtime activation. Credentials, runtime tokens, pending work, and private setup continuation are not portable state. Deploy additive API support and upgrade workers before enabling custom providers or releasing an SDK that uses these operations. Use public HTTPS or a reachable Dev Tunnel; a local-development flag does not grant private-network access. # Dev Tunnels Source: https://trytilde.ai/docs/dev-tunnels Let Tilde reach an agent running on your local machine. A Dev Tunnel gives your local application a stable public HTTPS endpoint. Tilde can use it to deliver ChatKit messages, webhooks, and tool invocations while you develop. ## Open a tunnel OpenBot owns Tilde authentication, state, tunnel, and plugin commands. ```bash theme={"system"} pnpm add -D openbot ``` Authenticate before opening the tunnel. The login flow opens Tilde and asks you to select a workspace. ```bash theme={"system"} pnpm exec openbot auth login ``` Run `pnpm exec openbot auth set-team` later if you need to switch workspaces. Replace `pnpm dev` with your normal development command. ```bash theme={"system"} pnpm exec openbot tunnel -- pnpm dev ``` The CLI opens a managed Cloudflare tunnel, chooses an available local port, and passes that port to your process as `PORT` and `TUNNEL_PORT`. It prints the public tunnel origin when the connection is ready. Keep the tunnel process running. Configure your local ChatKit agent with its endpoint path, then test it in [ChatKit workspace](https://api.trytilde.ai/chatkit-workspace). For a Next.js route at `app/api/agent/route.ts`, use `api/agent` as the local endpoint path in Tilde. Signed endpoint wrappers such as `chatKitEndpoint` verify Tilde's webhook signature before your agent code runs. Keep the signing key and other secrets on the server. The tunnel exposes every page and API route served by your development process—not only the agent endpoint—to the public internet. Disable unneeded routes or protect them with authentication before opening the tunnel. Stop the CLI process to close the tunnel. Replace the tunnel with your production endpoint before launch. # How to build a code review agent Source: https://trytilde.ai/docs/guides/code-review-agent # Frontend chat with your own authentication Source: https://trytilde.ai/docs/guides/frontend-chat Add a streaming ChatKit UI to your application using its own login provider and a server-only Tilde proxy token. Your users can sign in to your application and chat with a Tilde agent without signing in to Tilde. This guide uses Next.js route handlers and the Vercel AI SDK UI transport. The proxy also works in servers that support Fetch requests and responses. ```mermaid theme={"system"} sequenceDiagram participant Browser participant App as Your application server participant Tilde participant Agent as Your signed agent endpoint Browser->>App: Application session cookie + chat request App->>App: Verify session; resolve identity and permitted team App->>Tilde: Proxy token + org + acting identity + team route Tilde->>Tilde: Check identity, membership, and private session access Tilde->>Agent: Signed ChatKit turn Agent-->>Tilde: Response stream Tilde-->>App: UI message stream App-->>Browser: UI message stream ``` ## 1. Configure login and Tilde Set up your application's own login provider. For Clerk, follow the [official Next.js integration](https://clerk.com/docs/nextjs/getting-started/quickstart) using your application's Clerk keys, provider, sign-in/sign-up pages, middleware, and server session verification. Protect API handlers as well as pages. Sign in to Tilde and complete the first organization/team setup, or accept an invitation to an existing application organization. Organization/team creation is a native Tilde setup action; it does not depend on Clerk organization webhooks. Enroll the application organization in Core through Tilde administration. Create an [organization proxy token](/docs/identities/proxy-tokens) in **Settings → Organization → Proxy tokens**. Enable `runtime:delegate`, `identities:manage`, and `teams:manage` for first-login provisioning. Add `identity-links:create` only if you offer **Connect Tilde account**. ```dotenv theme={"system"} # Server-only Tilde configuration TILDE_API_ORIGIN=https://api.trytilde.ai TILDE_ORG_ID=org-your-application TILDE_PROXY_TOKEN=replace-with-your-secret ``` ```bash theme={"system"} pnpm add @trytilde/sdk @ai-sdk/react ai server-only ``` Use the SDK release that exports `@trytilde/sdk/proxy` and identity methods, together with the matching Tilde API deployment. Register a signed agent endpoint and its Vercel UI channel in the execution team, as described in [Set up ChatKit](/docs/chatkit#set-up-chatkit). Its agent API key and webhook signing key belong to that endpoint's server configuration. The browser uses the application proxy; it never receives these keys or the org proxy token. If each user gets a team, your trusted provisioning service must register the agent/channel in each team before users create conversations. ## 2. Persist a session-to-identity mapping Follow [identity provisioning](/docs/identities/index#provision-on-the-first-authenticated-request) to create or resolve the user's identity and initial team. Store the result in your database under the verified `(environment, issuer, subject)` key. Reuse it on subsequent logins and reconcile signed lifecycle webhooks. Create a server adapter named `resolveApplicationSession(request)` that returns `null` for an unauthenticated or disabled user, or: ```ts theme={"system"} return { identityId: mapping.identityId, teamIds: mapping.allowedTeamIds, }; ``` `mapping` comes from trusted persistence after verifying the session. Team selection from a browser is only a requested selection: check it against this list. Do not accept browser-supplied identity headers or grant access based on email equality. ## 3. Mount the runtime proxy ```ts app/api/tilde/[...path]/route.ts theme={"system"} import { createTildeProxy } from "@trytilde/sdk/proxy"; import { resolveApplicationSession } from "@/lib/application-session"; const proxy = createTildeProxy({ baseUrl: process.env.TILDE_API_ORIGIN!, orgId: process.env.TILDE_ORG_ID!, proxyToken: process.env.TILDE_PROXY_TOKEN!, mountPath: "/api/tilde", resolveSession: resolveApplicationSession, }); export { proxy as GET, proxy as HEAD, proxy as POST, proxy as PUT, proxy as PATCH, proxy as DELETE }; ``` Browser requests target `/api/tilde/api/v1/...` on your application's origin. The proxy supplies the token, organization, and acting identity on the upstream request. It allows supported runtime routes, checks the selected team, and keeps streams and request cancellation intact. Cookie-authenticated mutations must come from the same origin. ## 4. Create a private conversation Use the [server application client](/docs/identities/index#create-an-application-client) and the same session adapter for server-side calls. The following handler picks the user's mapped initial team. `agentForTeam` is your trusted lookup of the agent registered in that team; it must not return an arbitrary browser-submitted ID. ```ts app/api/conversations/route.ts theme={"system"} import { randomUUID } from "node:crypto"; import { tilde } from "@/lib/tilde"; import { resolveApplicationSession } from "@/lib/application-session"; import { agentForTeam } from "@/lib/agents"; export async function POST(request: Request) { if (request.headers.get("origin") !== new URL(request.url).origin) { return Response.json({ error: "Same-origin request required" }, { status: 403 }); } const session = await resolveApplicationSession(request); if (!session) return new Response(null, { status: 401 }); const teamId = session.teamIds[0]; if (!teamId) return new Response(null, { status: 403 }); const agentId = await agentForTeam(teamId); const runtime = tilde.forTeam({ identityId: session.identityId, teamId }); const conversation = await runtime.chatkit.createAgentSession({ agentId, lookupKey: `app:${session.identityId}:${randomUUID()}`, title: "New conversation", }); const participant = conversation.participants.find( (entry) => entry.participant_type === "human", ); const sessionId = conversation.session.id; const inboxId = participant?.inbox?.id; const instanceId = participant?.instance?.id; if (!sessionId || !inboxId || !instanceId) throw new Error("Chat participant missing"); const upstream = new URL(runtime.chatkit.vercelUiEndpoint({ sessionId, inboxId, instanceId, stream: true, })); return Response.json({ sessionId, streamUrl: `/api/tilde${upstream.pathname}${upstream.search}`, }, { headers: { "cache-control": "no-store" } }); } ``` Delegated workspace conversations have private ownership under the effective identity. Store the conversation ID in your application if you need to reopen it. For retryable creation, persist an application conversation key and reuse it as `lookupKey` instead of generating a new one on every retry. Reopening a stored ID still requires current Tilde session permissions. ## 5. Render the stream Call `POST /api/conversations` when the user starts a chat, then render this component with the returned `sessionId` and `streamUrl`. Use `sessionId` as the React key when switching conversations. The [AI SDK transport](https://ai-sdk.dev/docs/ai-sdk-ui/transport) sends messages to the same-origin endpoint. No Tilde authentication headers belong here. ```tsx components/chat.tsx theme={"system"} "use client"; import { useChat } from "@ai-sdk/react"; import { DefaultChatTransport } from "ai"; import { useMemo, useState } from "react"; export function Chat({ sessionId, streamUrl }: { sessionId: string; streamUrl: string; }) { const [draft, setDraft] = useState(""); const transport = useMemo(() => new DefaultChatTransport({ api: streamUrl, credentials: "same-origin", }), [streamUrl]); const { messages, sendMessage, status, error, stop } = useChat({ id: sessionId, transport, }); const busy = status === "submitted" || status === "streaming"; return
{messages.map(message =>

{message.role}: {message.parts.map((part, index) => part.type === "text" ? {part.text} : null, )}

)}
{error &&

The message could not be sent. Please try again.

}
{ event.preventDefault(); if (!draft.trim() || busy) return; void sendMessage({ text: draft }); setDraft(""); }}> setDraft(event.target.value)} disabled={busy} /> {busy && }
; } ``` The minimal renderer displays text. Add renderers for tool, file, and other message parts as your agent needs them. When reopening a conversation, load its history through the authenticated runtime transport and initialize the UI from that history. Do not recreate the session merely to load it. Use ChatKit's session attachment APIs for file uploads. Keep uploads under the same session authorization and proxy, and preserve their content type and body; do not turn binary bodies into JSON. Configure your hosting platform to permit streaming and your required upload sizes and durations. ## 6. Add realtime events when needed HTTP streaming is sufficient for a single active chat response. To observe background activity, request a fresh short-lived browser ticket through the proxy: ```ts theme={"system"} const encodedTeam = encodeURIComponent(teamId); const response = await fetch( `/api/tilde/api/v1/team/${encodedTeam}/identity/realtime-ticket`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ transport: "browser", origin: window.location.origin }), }, ); if (!response.ok) throw new Error("Realtime authorization failed"); const { ticket, protocol } = await response.json(); const url = new URL(`/api/v1/team/${encodedTeam}/chatkit/realtime`, tildeApiOrigin); url.protocol = url.protocol === "http:" ? "ws:" : "wss:"; url.searchParams.set("org_id", orgId); const socket = new WebSocket(url, [`${protocol}.${ticket}`]); ``` `tildeApiOrigin`, `orgId`, and `teamId` are public routing configuration. The token remains on your server. Tickets are one-use, origin-bound, and expire quickly; request a new ticket when reconnecting. Tilde revalidates identity membership and credential revocation during ongoing access. Close sockets and clear private client caches when the application session changes or signs out. ## 7. Offer account linking and check isolation Add [Connect Tilde account](/docs/identities/account-linking) in your application's settings if users should also open their identities through Tilde. This uses the managed hosted flow and does not add a paid seat. Before release, test two users in the same team and in different teams. Attempt to open each other's private session IDs, forge identity headers, reuse a revoked token, and reconnect after disabling an identity. Verify login/logout, repeat-login provisioning, streaming cancellation, uploads, and history loading with your actual identity provider configuration. # Host OpenBot with Tilde Cloud Source: https://trytilde.ai/docs/guides/hosted-openbot Create an isolated OpenBot installation, Vercel runtime, persistent Computer, and OIDC-backed AI Gateway access in one API call. Tilde Cloud can provision a complete [OpenBot](https://github.com/trytilde/openbot) installation from a title and a unique slug. The caller must be a system administrator or an administrator of the owning organization. ```bash theme={"system"} curl --request POST \ "https://api.trytilde.ai/api/v1/identity/organizations/$TILDE_ORG_ID/openbot/deployments" \ --header "authorization: Bearer $TILDE_ACCESS_TOKEN" \ --header "content-type: application/json" \ --data '{ "title": "Research workspace", "slug": "research-workspace" }' ``` The request creates or reconciles: * a dedicated Tilde team named `openbot-`; * an instance-only agent API key and OpenBot OIDC audience; * separate Vercel control and agent projects; * a persistent Vercel Sandbox used as the writable OpenBot Computer; * project-scoped Vercel OIDC for AI Gateway, Sandbox, and VCR access; * a deterministic `openbot--control.vercel.app` hostname; and * a non-interactive OpenBot initialization and production deployment command. The response has `status: "provisioning"` and includes the team ID, hostname, deployment URL, Vercel project names, Sandbox name, bootstrap command ID, and public OIDC registration. A repeated request with the same organization and slug reconciles the deterministic resources. A slug already owned by another organization is rejected. Custom `trytilde-fs.com` and `trytilde-dev-fs.com` hostnames are a follow-up. Provisioning currently uses the Vercel project domain so DNS does not block a working installation. ## Source control and credentials Hosted instances use OpenBot's `LocalGitProvider`. The writable checkout and its bare `file://` origin both remain on the persistent Sandbox filesystem; no GitHub account or GitHub token is required. Tilde's Vercel account token remains exclusively in the Tilde deployment worker. It is never passed to the Sandbox, Git repository, OpenBot SOPS document, or tenant project environment. Deployed agents use project OIDC for AI Gateway, while OpenBot sends content-addressed prebuilt releases through its team-scoped Tilde capability. Runtime configuration accepts user-owned model, agent, and generated Computer values. Tilde derives the API key, organization, team, hosted-instance identity, OAuth metadata, public origin, and Computer identity from the authenticated instance record rather than trusting caller-supplied values. ## Hosted inference billing Tilde Cloud forwards the non-secret hosted-billing marker to the agent runtime through the managed release configuration allowlist. Vercel tokens and static Gateway credentials remain excluded. OpenBot enables metering only for Tilde-managed project OIDC; direct owner Gateway-key and Codex subscription paths disable it. Before every Gateway model call, OpenBot reserves organization AI credits and prepares a worker- and generation-fenced AgentRun effect. It persists the Gateway generation for crash recovery. The authoritative generation receipt commits system or fallback cost and releases a BYOK reservation. BYOK still reserves first because Vercel may fall back to charged system credentials and requires Gateway credits for that fallback. An organization with zero Tilde AI credits cannot start a Gateway call, including a BYOK call. If a provider result is planned, uncertain, or reconciled without a recoverable model response, OpenBot does not repeat it. The old run fails safely, and a later owner message creates a new run. Hosted cost budgets use the authoritative receipt after each call, so `max_cost_microusd` can overshoot by the final call; the organization credit balance remains protected by pre-call reservation. ## Automatic memory OpenBot automatic memory is shipped and defaults off. Set `OPENBOT_AUTOMATIC_MEMORY_MODE` to `personal`, `personal_plus_agent`, or `team`, or use an `AGENT__AUTOMATIC_MEMORY_MODE` override. Only `personal_plus_agent` creates a lifecycle-owned bank. Its Agent Resource Bundle assigns the stable same-team `memory-catcher` ChatKit agent as synthesizer; omission preserves a current or server default, while disabling the bank removes that lifecycle-owned resource. Memory Catcher uses the installation's selected inference provider, including managed project OIDC, and owns no memory bank itself. Before a billed call it validates the exact current prompt chunk and unexpired worker lease with Tilde, then uses a durable AgentRun effect for reservation and authoritative settlement. Failed credit commit or BYOK release remains retryable without repeating provider inference. Its bank-bound tools require the current batch ID, complete evidence IDs, and fresh lease owner for every mutation and completion, so synthesis cannot recursively retain itself or reuse a stale claim. ## Managed release API After building `.vercel/output`, OpenBot creates a release for either `control` or `agents`, uploads each unique SHA-1 file through Tilde, finalizes the release, and polls it until `ready` or `failed`. | Method | Route | Purpose | | ------ | ---------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | | `GET` | `/api/v1/team/{team_id}/identity/openbot/instances/{instance_id}` | Read project, Sandbox, image, hostname, and lifecycle state | | `PUT` | `/api/v1/team/{team_id}/identity/openbot/instances/{instance_id}/configuration` | Install allowlisted tenant runtime values; platform credentials are rejected | | `PUT` | `/api/v1/team/{team_id}/identity/openbot/instances/{instance_id}/computer-image` | Record an immutable VCR digest owned by the instance control project | | `POST` | `/api/v1/team/{team_id}/identity/openbot/instances/{instance_id}/releases` | Create a control or agent release and declare its Build Output API manifest | | `PUT` | `/api/v1/team/{team_id}/identity/openbot/instances/{instance_id}/releases/{release_id}/files/{sha1}` | Upload one declared content-addressed file | | `POST` | `/api/v1/team/{team_id}/identity/openbot/instances/{instance_id}/releases/{release_id}/finalize` | Deploy all uploaded files to the server-bound Vercel project | | `GET` | `/api/v1/team/{team_id}/identity/openbot/instances/{instance_id}/releases/{release_id}` | Poll upload and Vercel deployment status | The release API never accepts a Vercel project ID from the caller. Tilde resolves the control or agent project from the authenticated hosted-instance record. Slugs must be lowercase DNS labels containing 3–48 letters, digits, or single hyphens. Titles must contain 1–100 characters. # Connect Linq messaging Source: https://trytilde.ai/docs/guides/linq Connect Linq once to provision messaging tools, ChatKit, Signals, and authenticated API access in Tilde. Linq connects iMessage, RCS, and SMS conversations to Tilde. One Linq common-provider installation provisions all supported surfaces from the same account: * 23 typed MCP messaging and account-management tools; * a ChatKit channel for inbound conversations and agent replies; * a Signals provider for Linq webhook events; and * a disabled-by-default Reverse Proxy profile for the Partner API V3. ## Before you start Create a Partner API token in [Linq API Tooling](https://dashboard.linqapp.com/api-tooling). Treat it as a secret. Tilde stores the token as an encrypted managed credential; it does not place the token in MCP schemas, fixed tool arguments, webhook URLs, or exported state. Decide which phone lines the installation should own: * Leave **Phone-line filters** empty to use the account's complete line pool and Linq failover. * Enter one or more E.164 numbers, separated by commas, to limit inbound routing and outbound defaults to that operational pool. * Create one Tilde installation per line when each line needs independent agents, access policy, or lifecycle. Use a shared installation when several lines should round-robin as one pool. ## Connect Linq 1. In Tilde, open **ChatKit** or **Tools** and add **Linq**. 2. Enter the Linq API token and an account or line-pool name. 3. Optionally enter the E.164 phone-line filters and choose a default ChatKit agent. 4. Complete setup once. Tilde provisions the Tool, ChatKit, Signals, and Reverse Proxy surfaces together; connecting Linq from either Tools or ChatKit produces the same installation. 5. Enable the Linq tools needed by an MCP server. The Reverse Proxy remains disabled until you explicitly enable it. The same bundle is preserved by Tilde state export as a `common_provider/installation` plus a pending `credential/setup_item`. After importing state, reconnect the API token once to restore every generated surface. Webhook signing secrets are generated again and are never exported. ## Webhooks For the managed Linq setup, **do not create a webhook subscription manually**. Tilde creates it through the Linq Partner API, subscribes to the events Linq currently accepts, stores the one-time Standard Webhooks signing secret, and removes the subscription when the common installation is deleted. The generated target has this shape: ```text theme={"system"} https://api.trytilde.ai/api/v1/webhooks/{linq-signal-endpoint-id}/events?version=2026-02-03 ``` The concrete URL is shown by the Tilde setup response and belongs to that Signals provider instance. Do not reuse another installation's endpoint. If you intentionally configure Linq as a standalone Signals provider instead of the common managed installation: 1. Create the Signals provider in Tilde and copy its generated webhook URL. 2. In Linq API Tooling, create a webhook subscription whose target is the copied URL with `?version=2026-02-03` appended. 3. Subscribe to the event families your automation needs. 4. Copy the returned `whsec_...` signing secret immediately into the Tilde setup field. Linq returns it only when the subscription is created. ## Supported events Tilde normalizes Linq message, reaction, poll, participant, chat, typing, phone-number, contact-card, payment, and connection events. Incoming `message.received` events can also open or continue a ChatKit session keyed by the Linq chat. Linq currently advertises four webhook names that its subscription-creation endpoint rejects: `payment.declined`, `payment.authorized`, `connection.created`, and `connection.revoked`. Managed setup detects explicit rejection and retries without only those names; the rest of the catalog remains subscribed. ## Go-live practices Design messaging for inbound-first conversations, space messages naturally, share contact cards early, and round-robin new users across active lines. Keep fallback lines warm. Do not exceed roughly 5,000–7,000 messages per day per line, include links or media in the first message, bombard non-responders, isolate Android users onto separate lines, or use iMessage for cold outreach. ## Verify the connection Use the Linq tools to list phone lines and chats, then send a reply to a conversation that has already messaged the line. Confirm that: * the recipient receives the text, reaction, or poll; * a `linq.message.received` Signal appears for an inbound reply; and * the matching ChatKit session receives the inbound message when the messages subscription is enabled. [Browse all Linq MCP tools](/docs/tool-providers/linq) or [learn how ChatKit providers work](/docs/chatkit). ## TypeScript SDK types `@trytilde/sdk-vercel-ai-node` exposes inbound Linq message metadata as `context.linq` with `LinqChatKitMessageMetadata`. Signals use the complete `LinqSignalType` union and the event-indexed `LinqSignalByType` map, so a `"linq.message.received"` handler receives a narrowed `LinqWebhookEnvelope<"message.received">` rather than untyped JSON. Register conversions under `onUnprocessed.linq` when loading ChatKit history: ```ts theme={"system"} const messages = await convertToAiSdkMessages({ messages: history.items, onUnprocessed: { linq: { "linq.message.received": async (signal) => ({ id: signal.id, role: "user", parts: [ { type: "text", text: `New message in ${signal.data.data.chat?.id}`, }, ], }), }, }, }); ``` # Link a Tilde account Source: https://trytilde.ai/docs/identities/account-linking Let an application user connect a Tilde login account to an existing runtime identity through a hosted confirmation flow. Offer **Connect Tilde account** when a user wants to access their application's runtime identity through Tilde. Their conversations, tools, private resources, and audit history stay attached to the same identity. ## Start a managed link Enable `identity-links:create` on the application's proxy token and register the exact return URL in **Settings → Organization → Proxy tokens**. In a server route, verify the application's session, check the same-origin mutation, and load the user's identity from your database. Call the unbound application client: ```ts theme={"system"} const linking = await tilde.linkIdentity({ identityId: mapping.identityId, returnUrl: "https://my-app.example/settings", }); return Response.json({ url: linking.url }); ``` Redirect the user to the returned URL. Tilde handles login and displays the initiating application, identity, and organization for confirmation. You do not need to implement a link-completion endpoint or exchange Tilde login cookies. The request is bound to the initiating application token, organization, and identity. It expires after 15 minutes and can be used once. Keep the URL out of analytics and logs. The configured return URL is a navigation destination, not proof that linking completed. ## Send a managed email ```ts theme={"system"} const linking = await tilde.linkIdentity({ identityId: mapping.identityId, returnUrl: "https://my-app.example/settings", delivery: { type: "email", address: verifiedRecipient }, }); ``` Use a recipient validated by your application. Tilde delivers the confirmation link and requires the destination account to match the designated verified recipient. Possessing an email-shaped runtime identifier does not establish verified contact ownership. ## Completion and conflicts Tilde authenticates the destination account and atomically claims the request. An expired, replayed, revoked-application, or conflicting request cannot create a new link. An identity already linked to another account cannot be claimed by signing in with a matching email address. Established account links let Tilde select the linked identity for that organization on later sessions. A new unlinked application identity needs the managed confirmation flow; do not automatically link it based on profile fields or an unverified issuer/subject identifier. Linking does not merge identities, add organization or team administration, move resources across organizations, or enroll an account seat. Direct Tilde runtime use requires explicit Core account-seat enrollment by an organization administrator. Your application's proxy access remains governed by its own session and the runtime identity's permissions. # Identities Source: https://trytilde.ai/docs/identities/index Create organization-owned runtime identities for people and agents, independently of login accounts. A runtime identity is the principal that owns private resources, receives grants, participates in ChatKit, and appears in tool and audit attribution. Your app can create one before its user has a Tilde login account. Your application controls login through its own Clerk application or another identity provider. Tilde controls runtime access inside your organization. ## Accounts, identities, and teams | Record | Purpose | Scope | | ------------------------ | ---------------------------------------------------------------- | ------------------------------------------------------ | | Login account | Sign in to Tilde and exercise explicitly assigned administration | Links to an identity in each organization | | Runtime identity | Own resources and act in tools, conversations, and audits | Exactly one organization; may belong to multiple teams | | Team | Group runtime resources and members | Exactly one organization | | Organization proxy token | Let a trusted application delegate runtime requests | Exactly one organization; may operate across its teams | An identity has a generated, stable ID, a `human` or `agent` kind, profile information, and enabled/disabled status. Its ID remains the same after [account linking](/docs/identities/account-linking), so its resources and history stay with it. Linking does not merge identities or grant administration. A useful application layout is one organization per environment and an initial team and identity for each user. Add team memberships when your application supports collaboration. An identity must currently belong to the team it acts in; knowing a team or resource ID does not grant access. ## Joining Tilde directly Tilde uses Clerk for login accounts, while organizations and teams are native Tilde records. Signing up does not create an organization in Clerk or provision a Tilde workspace through a webhook. If you follow an organization invitation from an email, sign in or sign up with the invited account. Tilde accepts the invitation, creates or reuses your identity in that organization, selects its team, and opens the home dashboard. Existing memberships in other organizations do not change that destination. For a first-time account without an invitation or organization membership, Tilde asks you to name your first organization and team. Submitting this setup creates the organization, team, identity, and administrative membership before opening home. Retries during initial setup reuse the same workspace instead of creating duplicates. Clerk webhooks reconcile account lifecycle only. If you completed first-organization setup previously but no longer have any organization memberships, Tilde shows **Restore organization access**. Recover access through an organization invitation or [managed account linking](/docs/identities/account-linking), or sign out to use another account. This recovery screen does not show the first-organization form. Tilde does not automatically recreate a deleted first organization or restore revoked access when the original setup request is retried. The hosted [account-linking flow](/docs/identities/account-linking) can connect an existing application identity without creating a separate first organization. ## Create an application client Create an [organization proxy token](/docs/identities/proxy-tokens) with identity and team provisioning capabilities. Store it only on your server. ```ts lib/tilde.ts theme={"system"} import "server-only"; import { createClient } from "@trytilde/sdk"; export const tilde = createClient({ baseUrl: process.env.TILDE_API_ORIGIN!, orgId: process.env.TILDE_ORG_ID!, proxyToken: process.env.TILDE_PROXY_TOKEN!, orgSubdomain: false, }); ``` The unbound client provisions identities and starts managed linking. Bind a new client to an identity and team for runtime requests: ```ts theme={"system"} const runtime = tilde.forTeam({ identityId: mapping.identityId, teamId: mapping.teamId, }); ``` `forTeam` returns a separate client. Keep the shared application client immutable so concurrent requests cannot exchange identities or teams. A bound runtime client cannot perform identity administration. ## Provision on the first authenticated request Verify the application's session on the server, including its expected issuer. Use the verified issuer and subject as the mapping key. Never use an identity ID, team ID, or email submitted by the browser as proof of identity. ```ts theme={"system"} import { IdentityApiError } from "@trytilde/sdk"; import { tilde } from "./tilde"; // Called after verifying the application session. async function provision(subject: string, issuer: string, displayName: string) { const identifier = { namespace: "my-app:login", value: JSON.stringify([issuer, subject]), }; let identity; try { identity = await tilde.createIdentity({ kind: "human", displayName, identifiers: [identifier], }); } catch (error) { if (!(error instanceof IdentityApiError) || error.status !== 409) throw error; identity = await tilde.identities.resolve(identifier); } if (identity.disabled) throw new Error("Application access is disabled"); const team = await tilde.identities.provisionTeam(identity.id, `${displayName}'s workspace`); return { identityId: identity.id, teamId: team.team_id }; } ``` Persist this result in your application database with a unique constraint on `(environment, issuer, subject)`. Serialize concurrent provisioning for that key and return the stored mapping on repeat login. The initial-team operation is idempotent; retry it after a partial failure. Do not retry arbitrary failures by creating another identity. Identifiers are optional and unique by `(org, namespace, value)`. You can add identifiers later with `tilde.identities.update`. An existing identifier cannot be claimed by another identity. Identifiers help your trusted server resolve a principal; they are not verified contact ownership or permission to link accounts. Matching email addresses alone never authorize a link. ## Manage memberships and identifiers An unbound client with `identities:manage` can manage an identity's memberships in existing teams within the same organization: ```ts theme={"system"} const teams = await tilde.identities.listTeams(identityId, { pageSize: 50 }); // teams.items contains this page; continue with teams.next_page_token. await tilde.identities.addTeam(identityId, additionalTeamId); await tilde.identities.removeTeam(identityId, additionalTeamId); await tilde.identities.removeIdentifier(identityId, { namespace: "my-app:old-id", value: "previous-subject", }); ``` Adding membership grants the runtime member role and preserves an existing role; it never assigns a login-account role. Removal revokes team membership and team groups while retaining the identity's resources. Disabled identities cannot be added to teams. Identifiers, verified contacts, and account links remain separate: removing an identifier does not unlink an account or transfer its resources. ## Manage lifecycle ```ts theme={"system"} const identity = await tilde.identities.get(identityId); const firstPage = await tilde.identities.list({ pageSize: 50 }); if (firstPage.next_page_token) { const nextPage = await tilde.identities.list({ pageSize: 50, nextPageToken: firstPage.next_page_token, }); } await tilde.identities.update(identityId, { displayName: "Alice Smith" }); await tilde.identities.update(identityId, { disabled: true }); ``` Identity and membership lists return `{ items, next_page_token }`. Pass cursors unchanged; page sizes are clamped to 1–100. Verify your identity provider's webhook signatures before changing a mapping. Record disabled/deleted state durably, reject stale events, and retry remote disabling after transient failures. Signing in again must not silently restore a deleted user's access. In HeyAsh, Clerk profile changes and unlock events do not re-enable a Tilde identity disabled by an administrator; recovery requires an explicit Tilde administrator action. Disabling an identity stops its runtime access while preserving resources and audit history. ## Fresh resets and stale events Before resetting Tilde or your application database, pause writers and record a cutover instant outside the databases being cleared. The Tilde and HeyAsh Clerk integrations support `CLERK_WEBHOOK_EVENTS_NOT_BEFORE` as an ISO-8601 timestamp with a timezone. Configure it on each deployment before bootstrap or webhook delivery resumes. Signed events older than that original-event timestamp are ignored; delivery retry timestamps must not bypass the cutoff. Keep lifecycle tombstones and signature verification in addition to this reset boundary. ## Authorization and billing The application proxy verifies its session and permitted team selection. Tilde then enforces the token's organization and capabilities, the identity's current status and membership, and the persisted resource's visibility and ownership. Private grants remain within their tenant. The token creator's administrator privileges do not become the delegated identity's privileges. Core subscriptions and usage belong to the organization. Runtime identities do not create paid account seats. Proxy requests and account linking never enroll or reactivate seats. Organization administrators explicitly assign account seats for people who use runtime features directly through Tilde. Next, configure [proxy tokens](/docs/identities/proxy-tokens), add a [frontend chat UI](/docs/guides/frontend-chat), or offer [Connect Tilde account](/docs/identities/account-linking). # Organization proxy tokens Source: https://trytilde.ai/docs/identities/proxy-tokens Issue and rotate server credentials that delegate runtime requests to identities in your organization. An organization proxy token lets your backend act as runtime identities across the organization's teams. It authenticates your application; the effective identity's current permissions determine which runtime resources it can access. ## Create and store a token 1. Sign in to Tilde as an organization administrator. 2. Select the organization and open **Settings → Organization → Proxy tokens**. 3. Choose **Create token**, enter an application/environment name, and select capabilities. 4. Set an optional expiry. Register exact return URLs if you enable managed linking. 5. Copy the one-time secret into your server's secret store. ```dotenv theme={"system"} TILDE_API_ORIGIN=https://api.trytilde.ai TILDE_ORG_ID=org-your-application TILDE_PROXY_TOKEN=replace-with-the-one-time-secret ``` Keep development and production organizations and credentials separate. Never use a public environment-variable prefix for the token. Only the origin and non-secret routing IDs may reach the browser. ## Choose capabilities | Capability | Allows | | ----------------------- | ------------------------------------------------------------------------------------------------ | | `runtime:delegate` | Act as an enabled identity on supported runtime routes; the default capability | | `identities:manage` | Create, resolve, update, disable, and manage memberships/identifiers for organization identities | | `teams:manage` | Provision an identity's initial team | | `identity-links:create` | Start a Tilde-hosted account-linking request | Enable only the capabilities the application uses. An application that provisions users and teams and offers account linking needs all four. You can use separate credentials for runtime traffic and provisioning if they run in separate services. Provisioning requests use the unbound application client. Runtime requests include an acting identity. The SDK browser proxy does not expose provisioning, token management, billing, account-link completion, or account administration. ## Mount the server proxy The SDK accepts standard Fetch `Request` and `Response` objects. In a Next.js App Router application, mount one handler for all supported methods: ```ts app/api/tilde/[...path]/route.ts theme={"system"} import { createTildeProxy } from "@trytilde/sdk/proxy"; import { resolveApplicationSession } from "@/lib/application-session"; const proxy = createTildeProxy({ baseUrl: process.env.TILDE_API_ORIGIN!, orgId: process.env.TILDE_ORG_ID!, proxyToken: process.env.TILDE_PROXY_TOKEN!, mountPath: "/api/tilde", resolveSession: resolveApplicationSession, }); export { proxy as GET, proxy as HEAD, proxy as POST, proxy as PUT, proxy as PATCH, proxy as DELETE }; ``` `resolveApplicationSession(request)` is your server adapter. It verifies your provider's session, checks your local lifecycle state, and loads the persisted identity/team mapping. Return `null` when unauthenticated, or: ```ts theme={"system"} return { identityId: mapping.identityId, teamIds: mapping.allowedTeamIds, }; ``` Do not populate `allowedTeamIds` from browser input. For a one-team-per-user app, return only the mapped initial team. For collaboration, load currently permitted teams from trusted membership data. Tilde independently validates membership. The proxy replaces inbound authentication and delegation headers, fixes the upstream origin, checks team selection, and preserves streaming, uploads, cancellation, and response status. Mutations require the browser's same-origin `Origin` header. Upstream credentials, cookies, and redirect locations are not forwarded to the browser. ## Wire format Server-to-server runtime calls carry: ```http theme={"system"} X-Tilde-Proxy-Token: X-Tilde-Org-Id: X-Tilde-Identity-Id: ``` The team is part of `/api/v1/team/{team_id}/...`. Keep identity delegation in its explicit header rather than adding it to resource request bodies. Do not combine proxy credentials with a login cookie, bearer token, or API key. Tilde rejects conflicting credentials and tenant routing. An organization token has a broader compromise scope than a single user's credential: a holder with runtime delegation can select identities across that organization. Your proxy must authenticate every request and constrain the team and identity, while Tilde enforces the final tenant and resource boundaries. ## Manage and rotate The table shows name, masked identifier, capabilities, creation and expiry, last use, and status. Administrators can rename, create a replacement, or revoke a token. Replacement creation leaves the old token active until explicitly revoked: 1. Create a replacement and store its new secret. 2. Deploy the new configuration and verify application requests. 3. Revoke the old token and confirm it no longer authorizes requests. A revoked or expired token cannot delegate requests. Realtime connections retain credential provenance and revalidate access; use short-lived browser tickets instead of exposing the organization token to a WebSocket client. See [Frontend chat with your own authentication](/docs/guides/frontend-chat) for the complete chat transport setup. ## Transport limits Org proxy credentials support the HTTP runtime surface described here. The SDK rejects org proxy credentials for gRPC reverse proxying until that transport has an equivalent delegation contract. Do not fall back to a different caller's credentials to make an unsupported transport work. The shared proxy sets restrictive content security and content-type headers on responses so navigated HTML or SVG cannot execute as your application. Fetch-based streams and binary uploads retain their normal transport behavior. SDK requests with application credentials reject redirects before contacting another origin. # Start building with Tilde Source: https://trytilde.ai/docs/index Build and operate TypeScript AI agents with secure tools, MCP servers, ChatKit, memory, skills, browser sessions, and portable Tilde configuration. Tilde breaks down what makes Claude Code, Codex, and OpenClaw effective and makes those capabilities available as an integrated product suite. Our mission is to open the hood on these products and give you the same building blocks. Tilde helps developers build purposeful AI agents quickly. The product suite includes: * **Tools:** Connect to hundreds of providers with off-the-shelf integrations, add custom tools, and group them in secure MCP servers. * **Memory:** Create a persistent brain and personal notebook for one agent, or share it across several agents. * **Skills:** Deploy skill registries that group instructions and make them available to agents. * **ChatKit:** Integrate with third-party chat providers, trigger agent runs from external webhook events, or schedule recurring prompts. These features are available through cloud APIs that hide the underlying complexity. Use our client-side library, `@trytilde/sdk`, with first-class support for Vercel and Next.js to build and deploy your own cloud agents. Build your first agent ## Explore the product suite Connect providers, add custom tools, and expose them through secure MCP servers. Connect conversations, webhooks, and scheduled agent runs. Organize reusable agent instructions in skill registries. Give one or more agents durable context they can recall. # Chatkit Source: https://trytilde.ai/docs/llms/chatkit # Configure ChatKit over Tilde Global MCP Use `https://api.trytilde.ai/mcp`. Call `tilde_whoami` first. Team ChatKit sessions, routines, and agents use `team` ownership; private resources use `user_team`, retaining both the effective owner and execution team. A private session may grant conversation access to selected team users. Every message, attachment, event, task, reply, and queued turn inherits its session audience. Agents, sessions, routines, signal providers, and signal rules have independent visibility and ownership modes. Visibility governs discovery, conversation/delivery reads, messaging, and realtime delivery. Ownership governs settings, membership, grants, target policy, and deletion. Ownership and administrator authority never imply visibility. Use the standard REST mode and user/group grant operations under the exact resource path published by OpenAPI. ## Build the endpoint first Start from the [Hello World agent](https://github.com/trytilde/examples/tree/main/hello-world-agent). For a provider-rich implementation, use the [code review bot](https://github.com/trytilde/examples/tree/main/code-review-bot). Browse the full [examples repository](https://github.com/trytilde/examples) before creating a new pattern. For Linq, create one common-provider installation from either ChatKit or Tools. Obtain the Partner API token from `https://dashboard.linqapp.com/api-tooling`; Tilde then provisions ChatKit, tools, Signals, and Reverse Proxy together and creates the signed Linq webhook subscription automatically. Do not ask the user to create a second webhook for the managed path. Use `/guides/linq` for phone-line scoping and the standalone Signals fallback. In `@trytilde/sdk-vercel-ai-node`, use `context.linq` / `LinqChatKitMessageMetadata` for inbound Linq ChatKit metadata and `LinqSignalByType["linq.message.received"]` (or another `LinqSignalType`) for event-narrowed Signal handlers under `onUnprocessed.linq`. With AI SDK 7, move server-authored system context into `instructions` before calling the model. Keep ordinary conversation and explicitly untrusted recalled memory in `messages`. Do not discard the server context to avoid a prompt validation error. Use Vercel AI SDK and Tilde SDK `chatKitEndpoint`. Preserve webhook signature verification, `context.session.history()`, `convertToAiSdkMessages`, streaming, and server-side secrets. ## Durable conversation work All work routes are bound to one agent and active session: * `.../agents/{agent_id}/sessions/{session_id}/goals` * `.../agents/{agent_id}/sessions/{session_id}/tasks` * `.../agents/{agent_id}/sessions/{session_id}/jobs` * `.../agents/{agent_id}/sessions/{session_id}/runs` Use the authenticated agent credential for mutations. Do not copy `agent_id` or `session_id` into request bodies. Goals accept `objective`; updates may set `status`, `progress_percent`, `progress_note`, and `status_reason`. Tasks accept `summary`, optional `goal_id`, `dependency_task_ids`, `plan`, and `metadata`; update the same progress/status fields as work advances. Delegate a job with `child_agent_id`, `objective`, `idempotency_key`, optional `model_id`, optional `metadata`, and optional `budget` containing `max_duration_seconds`, `max_input_tokens`, `max_output_tokens`, and `max_cost_microusd`. Use the exact action suffixes `/steer`, `/stop`, `/resume`, and `/collect-result`. Discover a real child agent ID first; never invent one. AgentRun hosts use `/active`, `/claim`, `/{run_id}/steps`, `/{run_id}/transition`, and owner `/{run_id}/control`. Record tool intent with `/effects/prepare`, look it up with `/effects/lookup`, and finish it with `/effects/finish`. Reuse committed outputs. Never automatically repeat an effect whose receipt is `uncertain`. Use the verified `context.execution` discriminated union: `agent_job` supplies `jobId`, `generation`, `childSessionId`, optional `modelId`, and optional `budget`; `agent_run` supplies `hidden`, `runId`, `workerId`, and `generation`. Ignore model-, budget-, run-, or worker-selection headers from callers. `chatKitAgentRunIdempotencyKey(triggerId, context.execution)` preserves ordinary trigger keys and qualifies job keys by trusted job ID and generation. Reuse the active run for a hidden continuation. For a hidden continuation, append the step with the supplied worker lease before transitioning. The transition’s `expected_generation` and `worker_id` fence an atomic acknowledgement of only the matching planned receipt, and only after a same-generation step newer than that receipt exists. Owner `/control` cannot finalize it, and an `uncertain` receipt is not automatically committed. Do not fabricate accounting to clear a failed invocation. ## Agent-owned context compaction POST lifecycle reports to `/api/v1/team/{team_id}/chatkit/sessions/{session_id}/compaction-events` with `agent_id`, `compaction_id`, and one lifecycle payload: * `started`: `input_message_count`, `estimated_input_tokens`, `compacted_through_message_id` * `ended`: `summary`, `compacted_message_ids`, `retained_message_ids`, `input_tokens`, `output_tokens` * `failed`: `error`, `retryable` Read `/compaction-events/latest?agent_id=...` for the last successful checkpoint. Read `/messages/from-last-compaction?agent_id=...&page_size=...` for that checkpoint plus retained/newer messages. The canonical transcript is never deleted or rewritten. Read `context.agent` when the endpoint needs its own canonical Tilde identity. It provides `id`, `displayName`, `providerId`, `status`, optional `principalUserId`, optional authenticated `avatar.url`, and lifecycle timestamps. Do not hardcode or separately fetch the receiving agent's name or avatar. Treat `context.agent` as optional during mixed-version rollout, and authenticate avatar requests with the same server-side Tilde credential. Set the required top-level `responseMode` to `agentLoop` or `tool`. In `tool` mode, assistant text is private reasoning and only `sendMessage` produces a visible ChatKit message. Use `context.session.tools` or `context.$provider.tools`; routing identifiers are server-bound and must never be requested from the model. `context.session.createMCPClient({ serverId })` exposes the same session-bound tools through MCP. For a private owner-workspace session, the authorized session also contributes the authenticated human's personal Memory and Wiki tools. The agent remains the credential actor; arbitrary personal connections are not federated and callers cannot nominate a user ID. Use `context.mcp.connect({ serverId })` for speaker-bound personal-tool federation on a shared agent. ChatKit supplies the verified speaker capability privately. Never accept a model- or caller-supplied user ID, account ID, or delegated capability. Unmapped external speakers receive no personal tools. ## Inspect outbound delivery Use `GET /api/v1/team/{team_id}/chatkit/session/{session_id}/message/{message_id}/deliveries` with the organization header and a credential that can read the message and session. The response is an array of `channel_inbox_id`, `provider_id`, `status`, optional `external_message_id`, `last_error`, and `delivered_at`. The optional `provider_status` is `pending`, `delivered`, or `failed` when final provider status can be queried. It overrides initial acceptance; Telnyx WhatsApp carrier failures return `dead_letter` with an error. Without that status, `delivered` only confirms provider acceptance. Neither is a read receipt. Wait on pending work and retain the same canonical message ID for uncertain notifications. A new attempt is safe only after a confirmed provider rejection. ## Manage multiplayer rooms A room is a ChatKit session. Use `/api/v1/team/{team_id}/chatkit/sessions/{session_id}/participants` for the roster and `/invitations` for invite/list operations. Use `/invitations/{invitation_id}/decision` to accept or decline, DELETE `/invitations/{invitation_id}` to revoke, and DELETE `/participants/{participant_instance_id}` to leave or remove. Only session ownership authority can create, inspect, or revoke invitations. Only the canonical `invitee_user_id` may accept or decline. Participant roles are `owner`, `admin`, or `member`; they are collaboration metadata and never override visibility/ownership authorization. Pending, declined, and revoked invitations expose no room transcript. Do not promise an OpenBot owner room UI yet. The typed API/SDK contract is available, but OpenBot keeps the UI dormant until canonical human identity discovery replaces raw user IDs. Provider actions currently include Slack/GitHub reactions and thread reads, Linq reactions and poll operations, and AgentMail thread reads. AgentMail `sendMessage` accepts `to`, `cc`, `bcc`, subject, HTML, and reply-all. Non-message actions appear as canonical `tool.execution` realtime events; `sendMessage` uses normal ChatKit message streaming. Participant visibility changes emit durable `participant.joined` / `participant.left` events with compact participant handles, display names, and external IDs when available. Workspace conversation snapshots return the same records in `participant_events`; keep them separate from `messages` and render them as session activity, not chat bubbles. Tilde includes the lifecycle context in agent history without invoking an agent turn. ## Register an agent Call `tilde_register_chatkit_agent` with: * `team_id` * optional `access_scope`: `team` (default) or `user_team`; private agent ownership is inferred from the effective caller * `display_name` * `endpoint_url`: an HTTPS URL in production, or an endpoint path such as `api/agent` for local development * `local_running_endpoint: true` for a Dev Tunnel endpoint * optional `concurrency_policy`: `queue`, `interrupt`, or `queue_and_batch` (defaults to `queue`) * optional `memory_bank_ids` to ingest this agent's conversations continuously The create response returns the plaintext Tilde API key and webhook signing key once, plus `message_tool_provider_id`. Give both secrets to the human for secure storage in the agent's server environment. Never print them into source, state, logs, or chat history. The message provider is credentialless and already bound to the new agent. Team agent create, update, and delete events are broadcast to authenticated ChatKit realtime connections for the team. Private agent lifecycle events are sent to current user or group visibility grantees. Realtime audiences are derived from current visibility and session membership on every event. A private visibility grant may admit an authorized user or group to the root, while private-session members receive that session's message and agent-turn stream. Client payloads do not expose authorization grants or internal audience identifiers. Human-created private workspace sessions belong to the authenticated human, including when a deployment service owns the selected agent. Tilde binds the workspace participant to that human for personal tool access. Delegated child sessions inherit the parent session's ownership. For owner-only WhatsApp/Linq ingress, update the channel with `provider_configuration.external_participant_policy` set to `{ "join": "linked_only", "agent_invocation": "linked_only", "personal_tools": "linked_participants", "session_scope": "personal" }`, preserving its other provider configuration. Shared verification uses the actual WhatsApp phone-number ID or configured Linq line as `provider_account_id`, not the destination channel ID. Ingress validates the real global link's route and current membership, materializes the channel's tenant identity, and stores the canonical verification namespace in the message actor. No duplicate verification link is created. Unverified or revoked senders do not join or wake the agent. Replies retain the incoming provider route; this setting does not select a background notification channel. ## Manage private session members Private sessions use `user_team` ownership. The creator is inserted as the owner automatically, and an optional `member_user_ids` list may add other users from the same team during creation. Use the private-session membership API to list, add, or remove non-owner members later. Do not confuse these authorization members with ChatKit inbox participants. Owners and team, organization, or system administrators manage membership. Members may list/read the session, send messages and attachments, and receive its ChatKit realtime message, delta, queue, turn, task, and error events. Members cannot change ownership or manage other members. A grant stops authorizing new access when the user is removed from the execution team. Realtime clients consume the closed `agent.*`, `session.*`, `participant.*`, `message.*`, `queue_item.*`, `turn.*`, `activity.*`, `task.*`, and `chat.error` union. They must refresh the workspace projection after `access.changed`. Use `PUT /api/v1/team/{team_id}/chatkit/workspace/sessions/{session_id}/read-state` with `{ "unread": false }` after presenting a session and `{ "unread": true }` for a manual unread override. Read state is per user and must never be copied into shared session metadata. ## Enable agent-to-agent messaging 1. Take `message_tool_provider_id` from the child agent's registration response, or find its `chatkit_agent_message` provider with `tilde_search_enabled_capabilities`. 2. Add both `chatkit_agent_message_send` and `chatkit_agent_message_wait_for_response` from that provider to the parent agent's runtime MCP server with `tilde_set_mcp_server_tool_enabled`. 3. Call the exposed `message` tool with `message.parts` and optional `message.metadata`. Pass `session_id` only to continue an existing child conversation. 4. Immediately call the exposed `wait_for_response` tool with the returned `ticket_id`. 5. Keep the MCP request open. Consume `message_streaming` and `agent_turn_status` progress notifications. Clients that omit an MCP progress token receive the same structured payload through `tilde.agent_response` logging notifications. 6. Use the final `response` as the canonical persisted ChatKit message. Terminal `status` is `completed`, `failed`, or `cancelled`; queue notifications report `pending` or `running`, the applied concurrency policy, trigger count, and whether the turn was batched. Bound tenant, target-agent, and ingress-channel fields are supplied by Tilde and cannot be overridden by the caller. Do not configure the removed pairwise internal-agent ChatKit channel. ## Propose a missing capability safely Agents can propose but cannot approve or execute capability changes. 1. POST the secret-free intent to `/api/v1/team/{team_id}/chatkit/self-extension-proposals`. Supply the exact `requesting_agent_id`, optional originating `session_id` and `run_id`, a stable `idempotency_key`, one supported `category`, a short title and rationale, and credential-free `desired_state`. Credential-shaped fields are rejected even when named as references or IDs; complete provider authentication only through the owner-authenticated setup continuation after approval. 2. Stop the agent turn after the client renders the returned capability-change Human Approval. Never treat a free-text yes as approval and never ask for API keys, passwords, OAuth codes, tokens, or signing keys in chat. 3. The owner client posts `approval_id`, `proposal_hash`, `proposal_generation`, and `decision: "approve" | "reject"` to `/api/v1/team/{team_id}/chatkit/self-extension-proposals/{proposal_id}/decision` using the authenticated human credential. The requesting agent's human owner or a team/system administrator may decide; agent credentials and unrelated humans are rejected. 4. Poll the proposal resource. Approved work moves through `approved`, `executing`, and `executed`; denied work becomes `rejected`. Leased retries are idempotent. 5. If the executed proposal contains a `provider_setup` continuation, hand its `setup_item_id` to the owner-authenticated generic credential setup flow. Resolve OAuth or credential next actions there; the agent must not receive authorization state or credential values. 6. Resume the original task only after the durable decision. Use the returned resource receipts for verification, not as authority to delete shared resources. Rollback is a separate authorized-human action and removes only receipts marked as proposal-created. Generated outputs remain encrypted and require the human-only consume-once endpoint. The delegated endpoint receives the authenticated caller's agent ID as `context.body.session.parentAgentId`. Direct sessions omit it. Use this server-authored value only when a specialist must continue caller-owned runtime context; never ask the model or client to provide the parent identity. ## Configure a ChatKit provider 1. Call `tilde_search_available_capabilities` with `kinds: ["chatkit_provider"]` and `include_schemas: true`. 2. Select the provider ID from the results. 3. Call `tilde_configure_chatkit_provider` with `provider_id`, `display_name`, the registered agent inbox ID, and any provider-specific configuration from the returned schema. 4. If setup requires human authorization, present the returned approval URL and wait with the returned continuation tool. 5. Call `tilde_search_enabled_capabilities` with `kinds: ["chatkit_channel", "chatkit_agent"]` to verify both resources. Use the Vercel AI Endpoint provider when the user wants to test the agent in [ChatKit workspace](https://api.trytilde.ai/chatkit-workspace). ## Search ChatKit conversations Use `GET /api/v1/team/{team_id}/chatkit/workspace/search` with the selected workspace's `team_id` and a required `q` parameter. Authenticate with the same API key or bearer token used for ChatKit workspace. * Omit `session_id` to search visible session titles, visible agent IDs and display names, and message bodies across the workspace. Private resources require a matching visibility grant. * Pass `session_id` to search messages only inside that session. * Set `page_size` from 1 to 100. The default is 25. * Pass the returned opaque `next_page_token` unchanged to fetch the next relevance-ordered page. * Inspect each result's `kind`: `session_title`, `agent`, or `message`. Every result carries session context; agent and message details appear only for their matching kinds. Queries must contain 1 to 256 non-whitespace characters. Search is case-insensitive full-text matching, not fuzzy or substring matching. A session scope that is hidden from the caller or outside the selected organization and workspace returns `404` without revealing whether it exists elsewhere. ## Configure coding-agent audit hooks Use `openbot plugin --cli --agent-id `. The command keeps MCP server and skill-registry setup in the same flow and installs native lifecycle hooks for the selected harness. Codex uses a packaged Tilde plugin; OpenCode uses a fail-open global plugin; Claude Code, Cursor, and Gemini CLI use their user hook settings. Gemini hooks return valid JSON on stdout, as required by Gemini CLI, while audit failures remain non-blocking. The adapters map one harness session to one tenant-scoped ChatKit session by a stable lookup key. They persist user prompts and final responses as ordinary ChatKit messages, then report tool start/completion/failure through `POST /api/v1/team/{team_id}/chatkit/agents/{agent_id}/tool-executions`. When a hook discovers a local tool one call at a time, its report includes the tool display name and immutable source identity; ChatKit activates that entry without treating unobserved catalog entries as removed. Do not create a separate audit table or transcript store. Search coding-agent messages through `/chatkit/workspace/search`, and read canonical tool execution events under the same session. Preserve the harness session ID and tool call ID when adapting another coding agent. Canonical tool details may contain sensitive inputs and outputs, so keep agent/session visibility narrow and rely on the ChatKit observability projection for browser disclosure. ## Trigger work with Signals Signals turn provider events into ChatKit messages. Signal providers and rules may be personal `user` resources with no owning team. A personal rule must supply `target_team_id`, and the owner must belong to that team. It cannot bind a fixed shared session; sessions it creates are `user_team` sessions for the same owner. Personal webhook providers currently use polling ingress, while team providers may use webhook or polling ingress. Provider/rule visibility controls discovery and delivery reads. Ownership controls configuration, target/session policy, grants, state-changing retries, and deletion. Deliveries inherit their rule; do not grant individual delivery rows. 1. Call `tilde_list_signal_providers` and inspect the selected provider's signal schemas and authentication requirements. 2. Call `tilde_create_signal_provider` with the provider-specific `body`. 3. Call `tilde_create_signal_rule` with a `body` that selects the event type, target agent, action, and stable session-key mapping. 4. Use one stable session key when related events should continue the same body of work, such as all updates to one Sentry issue or GitHub pull request. 5. Call `tilde_trigger_fake_signal` to test routing where the provider supports it. 6. Inspect execution with `tilde_list_signal_deliveries`. Use `tilde_retry_signal_delivery` only for a failed delivery that is safe to repeat. Use `tilde_list_signal_provider_instances` and `tilde_list_signal_rules` before updating or deleting resources. Their mutation functions are `tilde_update_signal_provider`, `tilde_delete_signal_provider`, `tilde_update_signal_rule`, and `tilde_delete_signal_rule`. In application code, handle typed GitHub, Slack, Sentry, and Firecrawl metadata as shown in the [human ChatKit guide](https://trytilde.ai/docs/chatkit). `onUnprocessed` runs once per unprocessed message; later conversions reuse its cached result. ## Agent-owned realtime audio Use the selected tenant host and explicit `team_id` for these REST operations: 1. `GET /api/v1/chatkit/audio/profiles` returns supported profile defaults and server-authored fields. Render these descriptors rather than generating provider-specific setup instructions in frontend code. 2. Register an HTTP agent with optional `audio` configuration, or use `PUT /api/v1/team/{team_id}/chatkit/agents/{agent_id}/audio` with `{ "audio": }`. Set `audio` to null on the PUT route to disable voice. 3. Configuration fields are `mode` (`pipeline`, `realtime`, or `telnyx_relay`), `credential_id` (optional), `stt_model`, `tts_model`, `realtime_model`, `voice`, `instructions`, `language` (default `en-US`), `interruptible` (default true), and `max_duration_seconds` (10–1800). The OpenAI Audio credential source is `chatkit_openai_audio`; omitting it uses the server OpenAI key for OpenAI modes. Relay uses `stt_model: "deepgram/nova-3"`, `voice: "Telnyx.Ultra.Callie"`, and null `credential_id`; its phone route owns the Telnyx credential. 4. `POST /api/v1/team/{team_id}/chatkit/agents/{agent_id}/audio/sessions` creates a normal browser session for OpenAI modes and returns `audio_session`, `websocket_path`, and a one-time token. Connect with WebSocket subprotocols `chatkit-audio` and `token.`. This endpoint rejects `telnyx_relay`; relay starts from an incoming call. Send mono signed PCM16 little-endian audio at 24 kHz as base64 `audio` frames. 5. `PUT /api/v1/team/{team_id}/chatkit/agents/{agent_id}/audio/telnyx` accepts `credential_id` (source `chatkit_telnyx_voice`), `public_key`, `phone_number`, `connection_id`, and public HTTPS `media_base_url`. It returns `route` and `webhook_url`; successful setup also returns the assigned `route.channel_inbox_id`. Use the webhook URL in the dedicated Telnyx application. 6. The generic channel catalog entry is `chatkit.chat_channel.telnyx_voice`, provider `chatkit.channel.telnyx_voice`. Use auth method `chatkit.channel.telnyx_voice.auth.self_managed` for a returned URL or `chatkit.channel.telnyx_voice.auth.managed` for Tilde to update the existing Voice API application's webhook. Both use your existing encrypted `chatkit_telnyx_voice` credential and existing number/application. Pass the same five setup fields and the normal default agent selection. Managed setup updates webhook configuration; it does not buy, assign, or fund numbers. Calls use the resulting channel as their participant origin. Pipeline mode invokes the existing callback only when a user speech turn is ready. Rust synthesizes the response. Relay invokes the same signed callback with `context.audio.mode = "telnyx_relay"`; Telnyx transcribes and synthesizes, while Tilde exchanges text frames with the carrier. Realtime mode owns spoken generation; transcript observations must not trigger another model turn or external send. `context.audio` and `context.telnyx` come from typed, server-authored speech provenance rather than client message metadata. Both persisted text and UI messages can carry `speech`. Interrupted generated speech retains its original text with `interrupted: true`, optional `played_audio_ms`, and optional `reported_spoken_text` supplied by the carrier. Preserve the reported prefix separately; do not rewrite it as the complete generated response. SDK history conversion adds the corresponding annotation before the original content. The manual browser/carrier example is `examples/realtime-voice` in `trytilde/dispatch` (the `@trytilde/sdk` packages). It never buys phone numbers or changes existing carrier routing. Agent settings and credential setup references are portable; live connections and media tokens are not exported. Configure Telnyx number/application bindings again in the destination installation. Native mode does not inherit endpoint tools, and browser voice does not establish personal-tool federation. ## Change resources through native tools Agents use native Tilde API/MCP operations under their existing permissions. The capability proposal API has been retired. Chain dependent operations using returned resource IDs, reconcile partial failures before retrying, and read back the resulting resource. Do not widen permissions or switch credentials after an authorization failure. Before enabling a connector, read the managed [enable-connections skill](https://docs.trytilde.ai/llms/connections.md). Discover existing user and agent access and verify the correct account first. Choose personal/user or bot ownership explicitly; when unclear, ask whether other bots should be able to use the account. Native brokering returns a `connector_setup_required` descriptor for the pending resource. API clients render an enable-provider event outside message bubbles and open secure configuration modals. In external channels, invoke sendMessage with the server-returned hosted setup URL. Credentials stay in native secure setup operations, outside chat and persisted client workflow snapshots. ## Recover missing conversation context Session-scoped MCP connections provide `chatkit_search_history`. The query searches the current conversation by default. Set `include_related_sessions` to search other conversations that the authenticated agent actively participates in with the current session's verified human owner. Ordinary search permissions also apply. Models cannot supply a different agent, tenant or user identity to this tool. Follow `next_page_token`, even after an empty filtered page. ## Manage custom ChatKit backends Call `tilde_manage_custom_chatkit_provider` in the resolved team scope. Supported `action` values are `create`, `list`, `get`, `update`, `refresh`, `enable`, `disable`, `delete`, and `rotate_signing_key`. Use `provider_id` for an existing definition. Create/update use `display_name`, `discovery_url`, and optional `local_running_endpoint`. Create returns a pending definition and one-time signing key. Configure the customer-hosted endpoint with that key and definition ID before refreshing. Never place signing keys or runtime credentials in shared conversation history. Use the generic provider setup catalog/start/resume operations with domain `chatkit` and the definition ID; follow the returned `next_action`. Session tools are discovered against the authenticated agent's current turn. Do not fabricate session coordinates, use a provider runtime token as a user credential, or expose transport context as model inputs. Preserve tool-call IDs for replay and rely on canonical execution receipts and reconciliation. A failed discovery refresh preserves the last valid manifest. Disabled providers pause runtime work. Definition deletion fails while connections refer to it. Portable imports remain pending until fresh credentials are bound. See [custom ChatKit providers](https://docs.trytilde.ai/custom-chatkit-providers) for the public SDK authoring contract. # Connections Source: https://trytilde.ai/docs/llms/connections # Enable connections Use this managed Tilde skill before enabling a provider, choosing an account, or mapping connector tools. Native permissions control which operations the caller can perform. Chain the native API/MCP functions; do not create capability proposals or add a separate approval ceremony. ## Discover before changing anything 1. Identify the authenticated user, requesting agent, current session, and source channel from trusted runtime context. Read the relevant native records when an identifier is missing; do not infer identity or permissions from message prose. 2. Search the agent's enabled tools and the target user's enabled resources for the needed capability. Read the account identity (for example the Gmail address) and enabled functions. If the correct account and required functions are already usable, continue the task with no setup UI. 3. If multiple accounts could fit, ask which account to use. Do not add a duplicate provider account to avoid resolving the choice. ## Choose ownership and access * Prefer a user/personal connection when it is the user's account and should be reusable by their other bots. * Use an agent/bot connection when the account is explicitly dedicated to that bot and should not be generally available to the user's other bots. * If unclear, ask: “Should your other bots also have access to this account?” A yes normally means user/personal ownership; a no normally means this bot's MCP. * Discover the exact target MCP/resource IDs and inspect existing mappings. The agent's own bundle IDs are not substitutes for the user's IDs. ## Enable and broker 1. Discover the provider and credential-source IDs from `tilde_search_available_capabilities`; use returned schemas. Never guess IDs. 2. Invoke the native enable/setup operation, such as `tilde_enable_toolkit_provider` or provider auto-provisioning, with the selected ownership/target. Reuse an existing account whenever possible. 3. When the operation requires OAuth, managed credentials or an API key, its structured setup result drives the client. In API chat, the client renders one “Click to enable Provider” event card outside message bubbles and opens secure setup modals. Do not emit an extra account-selection card before discovery, and never ask for credential values in chat. 4. In WhatsApp, iMessage, Slack and other non-API channels, rich client modals are unavailable. Use the channel's `sendMessage` operation to send the server-returned broker URL or the supported Heyash/Dispatch/Tilde hosted setup URL. Use the native session/channel addressing from context. Do not invent a URL, send private tokens separately, or assume the recipient can see an API-chat card. 5. Follow the returned continuation/wait operation until credentials are active. On cancellation or failure, report the specific state; retry the same setup rather than creating a duplicate. ## Map and verify Enable only the required provider functions, then map them to the selected user's or bot's MCP with native tool-enablement/mapping operations. Keep dependent calls ordered: first obtain the actual account/resource IDs, then use them in later calls. `MULTI_EXECUTE_TOOL` is a batching convenience, not a substitute for dependencies or authorization. Read back account identity, active status and target MCP mappings before resuming the original task. Respect authorization errors; do not widen permissions, impersonate another user, copy credentials between owners, or fall back to a different account silently. # Dev tunnels Source: https://trytilde.ai/docs/llms/dev-tunnels # Configure local agents with Tilde Dev Tunnels Global MCP configures the local endpoint, but it cannot start a process on the user's machine. The authenticated tunnel command is a local CLI step. ## Global MCP step Call `tilde_register_chatkit_agent` with: * the target `team_id` * `display_name` * `endpoint_url` set to the local route path, for example `api/hello-world` * `local_running_endpoint: true` Give the returned API key and webhook signing key to the human for secure server-side storage. ## Local CLI steps Ask the user or local coding agent to run: ```bash theme={"system"} pnpm add -D openbot pnpm exec openbot auth login pnpm exec openbot tunnel -- pnpm dev ``` Replace `pnpm dev` with the application's normal development command. If the selected workspace is wrong, run `pnpm exec openbot auth set-team`. The CLI starts a managed Cloudflare tunnel and passes the chosen local port to the process as `PORT` and `TUNNEL_PORT`. Keep the process running while Tilde delivers ChatKit messages, webhooks, and tool invocations. Signed Tilde SDK wrappers such as `chatKitEndpoint` reject ChatKit requests without a valid Tilde signature. That protects the wrapped agent endpoint; it does not secure unrelated routes. **Warning:** the tunnel exposes every page and API route served by the development process to the public internet. Disable unneeded routes or protect them with authentication. Test the registered agent in [ChatKit workspace](https://api.trytilde.ai/chatkit-workspace). Select the same workspace before starting a session. See the [human Dev Tunnels guide](https://trytilde.ai/docs/dev-tunnels). # Memory Source: https://trytilde.ai/docs/llms/memory # Configure memory over Tilde Global MCP Tilde has two related knowledge resources: * A **memory bank** stores durable semantic memories and supports recall, retain, reflect, and deletion. * A **wiki** stores structured Markdown pages, schemas, relationships, revisions, graph data, and assets. Schema packs are reusable page and relationship schemas applied to a wiki; they are not a third memory system. Use `https://api.trytilde.ai/mcp`. Call `tilde_whoami` first. Memory banks and wikis may be `team` or personal `user` resources; personal REST routes use `/api/v1/user/{user_id}/...` and do not carry a team ID. Both roots have independent visibility and ownership modes. Visibility is required for list/get/read and memory or wiki content operations. Ownership is required for bank configuration, source policy, wiki schema/settings, grants, lifecycle, and deletion. User/group ownership grants and administrator status do not imply visibility. Pages, revisions, assets, memories, source projections, and generated tools inherit the root planes. Use the standard REST `/{id}/visibility`, `/{id}/ownership`, and `/{id}/{plane}/grants` operations under the team or personal bank/wiki path. Private group grants must name a same-tenant Identity group. A personal target may consume a workspace source the caller can see, but a workspace target cannot bind a personal source. Do not copy a personal source into durable workspace projections. Memory-bank and wiki ownership can move between `user` and `team` through their dedicated `/ownership` operation. Detach and purge source bindings first. The API does not expose transfer to a different user. ## Memory banks 1. Call `tilde_list_memory_providers` to confirm the hosted provider. 2. Call `tilde_create_memory_bank` for a workspace bank or `tilde_create_personal_memory_bank` for the authenticated human's private bank, with a clear name and purpose. 3. Save the returned memory bank ID. 4. Use `tilde_get_memory_bank` and `tilde_check_memory_bank_health` to verify provisioning. Memory banks use Tilde's managed Helix graph and vector store. Tenant and bank predicates scope every query and mutation. Recall fuses semantic, lexical, exact-title, and graph candidates before reranking a bounded result set with evidence, source, and learning-agent provenance. Callers never supply raw tenant or graph predicates. Retained documents use typed `memory_type`, `title`, `importance`, `authorship`, `relations`, and `provenance` fields. Put evidence IDs, subjects, supersession, source identity, and learning-agent identity in those fields. Use `metadata` only for provider-native or caller-owned extension facts that Tilde does not interpret. ## Automatic ChatKit memory Set `automatic_memory_mode` on the ChatKit agent or channel to exactly `none`, `personal`, `personal_plus_agent`, or `team`; default to `none`. `memory_bank_ids` controls conversation ingestion and is not a substitute for recall authorization. For one recipient-bound recall, POST `/api/v1/team/{team_id}/chatkit/agents/{agent_id}/sessions/{session_id}/automatic-memory/recall` with the durable triggering `message_id` and optional `max_tokens`. Never supply or infer a user ID. Tilde derives the effective actor from the stored message/session and returns only visible, provenance-bearing memory. OpenBot automatic-memory wiring is shipped and default-off. Persist `OPENBOT_AUTOMATIC_MEMORY_MODE` or a per-agent `AGENT__AUTOMATIC_MEMORY_MODE` override. `personal_plus_agent` alone provisions an agent-owned bank; `personal` and `team` enable their corresponding authorized recall without creating that bank. Memory Catcher uses the installation's selected Codex, direct Gateway, or managed-OIDC inference provider and has mode `none` plus no bank of its own. For an Agent Resource Bundle, `memory.bank.synthesizer_agent_id` is an optional stable same-team ChatKit agent key. Set it to `memory-catcher` for an OpenBot-owned bank. Omission preserves the current or server-default synthesizer; it never clears an assignment. `memory.bank.enabled: false` deletes the lifecycle-owned bank. Portable state carries the synthesizer as a ChatKit agent resource reference and resolves it in the destination team. ## Personal-bank synthesis PUT `/api/v1/user/{user_id}/memory/banks/{bank_id}/synthesizer` with `synthesizer_agent_id` and `synthesizer_team_id`. The authenticated human must own the bank. Tilde creates a stable private synthesis session and queues visible completed-turn evidence. The assigned agent uses these session-bound paths: * `POST /api/v1/team/{team_id}/memory/synthesis-sessions/{session_id}/validate-batch` * `POST /api/v1/team/{team_id}/memory/synthesis-sessions/{session_id}/recall` * `POST /api/v1/team/{team_id}/memory/synthesis-sessions/{session_id}/retain` * `DELETE /api/v1/team/{team_id}/memory/synthesis-sessions/{session_id}/documents` DELETE the bank's `/synthesizer` assignment to stop processing while retaining queued evidence. For synthesis retain, supersede, forget, and completion, copy the exact current `batch_id`, complete duplicate-free `evidence_ids` in their supplied order, and fresh `lease_owner` supplied by the job. Never reorder the evidence sequence or reuse a prior claim's lease. OpenBot exposes these as the bank-free `memory_upsert`, `memory_supersede`, `memory_forget`, and `finish_synthesis` tools; Memory Catcher must finish the durable receipt before emitting the requested completion marker. Before inference, call `validate-batch` with the batch ID, exact ordered evidence-ID sequence, and lease owner. Tilde recomputes the digest and accepts only the current prompt-sized evidence chunk under the unexpired lease. Each later mutation repeats the same typed binding, so a stale worker, reordered set, or arbitrary subset cannot authorize a mutation or completion. ## Organization AI credits These are agent-authenticated billing operations, not Global MCP tools: 1. POST `/api/v1/billing/ai-credits/reservations` with `estimated_cost_microusd` and `idempotency_key` before inference. 2. POST `/api/v1/billing/ai-credits/receipts` with `reservation_id`, `actual_cost_microusd`, `model_id`, `input_tokens`, `output_tokens`, `tags`, and `idempotency_key`; include `generation_id` and `provider` when available. 3. DELETE `/api/v1/billing/ai-credits/reservations` with `reservation_id` when no provider charge occurred. OpenBot hosted-inference metering is shipped for every Tilde-managed Vercel project-OIDC Gateway call, including Memory Catcher. Before each call, reserve credits and prepare a generation- and worker-fenced AgentRun effect. Persist the Gateway generation for recovery. Commit authoritative system/fallback receipts and release authoritative BYOK receipts. Direct owner Gateway keys and Codex subscription inference are outside this meter. Do not let BYOK skip reservation: Vercel may fall back to charged system credentials, so zero-credit organizations cannot start any Gateway call. Do not replay planned, uncertain, or reconciled effects. If no model response is recoverable, terminally fail the old run; a later owner trigger creates a new run. Hosted `max_cost_microusd` uses authoritative post-call receipt cost and may overshoot by one final call. Non-hosted cost budgets require configured input/output price rates. Human top-up authorization remains separate. ## Wikis and schema packs 1. Call `tilde_create_wiki` for workspace knowledge or `tilde_create_personal_wiki` for the authenticated human. Set same-scope `memory_bank_ids` when its content should also be ingested into memory. 2. Call `tilde_list_wiki_schema_packs` to inspect reusable schemas. 3. Call `tilde_apply_wiki_schema_pack` with `wiki_id` and `schema_pack_key`. Tilde records the authenticated caller as the actor. 4. Use `tilde_get_wiki` to verify provisioning. Use `tilde_retry_wiki_provisioning` only after an errored provisioning attempt. `tilde_update_wiki` can rename a wiki and replace its complete memory-bank selection. An empty `memory_bank_ids` array detaches it from all banks. ## Continuously ingest sources Call `tilde_set_memory_source_bindings` to replace the complete bank selection for a source. Supply: * `source_kind`: `chatkit_channel`, `chatkit_session`, `signal_provider`, `signal_delivery`, `skill_registry`, `skill`, `mcp_server`, `wiki`, or `wiki_page` * `source_id`: the configured resource ID * `memory_bank_ids`: target bank IDs; pass an empty array to detach the source ChatKit agents and wikis can also accept `memory_bank_ids` when created. Use explicit source bindings for other resources or when changing bindings later. Inspect ingestion with `tilde_list_memory_bank_sources`. Call `tilde_retry_memory_sync` with the source kind and ID after fixing the cause of a failed sync. For personal Signal providers and personal Wikis, call `tilde_set_personal_memory_source_bindings`. Tilde infers the human user from authenticated credentials; never supply or guess a user ID. A personal source can bind only to a personal bank owned by that user in the same organization. New deliveries and Wiki changes are queued automatically after the explicit binding is created. ## Expose memory and wiki tools Creating a bank or wiki automatically enables a private tool provider. It does not expose those functions on an agent's MCP server. 1. Call `tilde_search_enabled_capabilities` for the bank or wiki name. 2. Select the exact tool functions the agent needs. Avoid destructive functions unless required. 3. Map each function to the agent's runtime MCP server with `tilde_set_mcp_server_tool_enabled`. 4. Prefer dynamic mode for the full wiki toolset. Treat the wiki as the source of truth for structured and relational knowledge. A useful maintenance pattern is a daily agent run that reviews the previous 24 hours, updates the wiki first, and retains only concise durable facts that do not belong in the wiki. See the [human Memory guide](https://trytilde.ai/docs/memory). ## Background synthesis Assign one synthesizer agent to each bank. Tilde queues source evidence by bank and invokes the assigned agent when the queue reaches 1,000 estimated tokens. The synthesis session exposes only that bank's tools. Every retain, supersede, or delete command is bound to the exact batch, evidence IDs, and worker lease. The agent must complete the batch with `mutated` or a cited `noop` outcome. Owner-written explicit facts are protected from automatic overwrite and deletion. Synthesis leases and receipts are operational state and are not part of exported bank configuration. Every bound Wiki provides `grep_pages` in addition to full-text `list_pages`. Use literal mode for exact text and regex mode for patterns. Results contain stable page identity, path, one-based line number, the matching Markdown line, and bounded context; page and match limits prevent unbounded scans. # Openbot Source: https://trytilde.ai/docs/llms/openbot # Hosted OpenBot Create a complete cloud-hosted OpenBot instance with the REST API. This is organization-admin work and is not a team-scoped Global MCP function. `POST /api/v1/identity/organizations/{org_id}/openbot/deployments` ```json theme={"system"} { "title": "Research workspace", "slug": "research-workspace" } ``` Use a human bearer token when acting for an organization administrator. The slug is a globally unique lowercase DNS label of 3–48 characters. The call creates a dedicated `openbot-` team, agent-owned instance API key and OIDC audience, Vercel control and agent projects, persistent Vercel Sandbox, project-OIDC AI Gateway access, a deterministic `openbot--control.vercel.app` hostname, and starts OpenBot deployment. That installation API key can create and reconcile ChatKit agents under its ordinary team permissions. Custom Cloudflare hostnames are a follow-up and do not block provisioning. The response returns `status: "provisioning"`, `team_id`, `hostname`, `deployment_url`, `vercel_control_project`, `vercel_agent_project`, `vercel_sandbox`, `bootstrap_command_id`, and `oauth`. Repeating the request reconciles deterministic infrastructure for the same organization and slug. Hosted Git is local to the persistent Sandbox. Do not add GitHub credentials unless the owner later chooses an external forge. Never copy the Tilde-owned Vercel token into the repository, SOPS document, logs, or project environment. Tilde-managed Vercel project OIDC enables OpenBot hosted-inference billing. The managed release forwards only the non-secret billing marker; it never forwards the Vercel token or a static Gateway key. Reserve organization AI credits before every Gateway call. Persist intent and generation through the current AgentRun effect ledger. Commit authoritative system/fallback receipts and release authoritative BYOK receipts. Vercel BYOK can fall back to charged system credentials, so BYOK does not bypass reservation and zero-credit organizations cannot start Gateway calls. Direct owner Gateway keys and Codex subscription inference remain outside hosted metering. Never replay a planned, uncertain, or reconciled inference effect. If billing can be reconciled but the model response cannot be recovered, terminally fail the old run; a later owner trigger creates a new run. Hosted run cost uses the authoritative receipt after each call. A run-level `max_cost_microusd` guard can overshoot by that final call, while the organization balance is still preflight-gated. OpenBot automatic memory is shipped and defaults to `none`. Persist `OPENBOT_AUTOMATIC_MEMORY_MODE` or `AGENT__AUTOMATIC_MEMORY_MODE`. Only `personal_plus_agent` provisions an owned bank. The bundle field `memory.bank.synthesizer_agent_id` names a stable same-team ChatKit agent key; OpenBot uses `memory-catcher`. Omission preserves the current/server-default assignment, and `memory.bank.enabled: false` deletes the lifecycle-owned bank. Memory Catcher inherits the selected Codex, direct Gateway, or managed-OIDC inference adapter and submits every synthesis mutation and completion with the job's exact batch, complete evidence set, and fresh lease owner. For managed OIDC, Memory Catcher must call the synthesis session's `validate-batch` endpoint before creating its AgentRun, reserving credits, or invoking Gateway. Tilde accepts only the deterministic current prompt chunk under the active lease. Use generation-stable effect identity with current generation/worker-fenced writes. Retry a committed credit receipt or BYOK release without another reservation or provider call, then terminally fail the response-less run. For redeployment, use the team-scoped hosted-instance routes under `/api/v1/team/{team_id}/identity/openbot/instances/{instance_id}`. Create a service-specific release, upload each declared SHA-1 Build Output API file, finalize it, then poll the release. Never send a Vercel project ID: Tilde derives it from the hosted instance. Runtime configuration accepts only user-owned OpenBot values and rejects Vercel, AWS, SOPS, static AI Gateway, and caller-supplied Tilde tenant credentials. Tilde installs canonical tenant, OAuth, origin, and Computer identity from authenticated server state. Computer image updates must be immutable `vcr.vercel.com/...@sha256:...` references owned by the instance control project, which also owns the persistent Sandbox. # Skills Source: https://trytilde.ai/docs/llms/skills # Configure skills over Tilde Global MCP A skill is a focused instruction document. A registry groups skills and exposes progressive discovery tools so an agent loads full instructions only when relevant. Tilde also synchronizes trusted upstream `SKILL.md` providers. Built-in sources are restricted to official repositories and, for monorepos such as Cursor plugins and YC Software QM, server-authored include and exclude paths. QM contributes only its portable `popular-web-designs` and `taste-skill` packages; runtime-specific QM administration, credential, connector, memory, browser, and publishing instructions are excluded. Do not construct arbitrary trusted-provider URLs or assume that every MCP provider publishes skills. Select only skills returned by Tilde's provider and skill listing functions. Successful provider syncs retain each complete bounded skill package: `SKILL.md` plus package-local references, templates, scripts, examples, and media. Relative paths and media types are preserved; unsafe paths and symbolic links are rejected. Sync is failure-atomic, so an unreadable or invalid file does not purge the last valid provider snapshot. Deleted and renamed upstream skills stop being advertised only after a complete successful reconciliation. Exported state embeds selected package files with checksums so import can verify and recreate every referenced asset in the target workspace. It never includes a plaintext credential or an unverified repository payload. When a loaded `SKILL.md` refers to another package file, call `GET /api/v1/team/{team_id}/skill/{skill_id}/package` to inspect the immutable manifest. Then call `POST /api/v1/team/{team_id}/skill/{skill_id}/package/download` with the manifest `path` to obtain a short-lived download URL. For example, if the manifest contains `examples/analyze.py`, download and access it like this: ```bash theme={"system"} API_BASE="https://api.trytilde.ai/api/v1" MANIFEST=$(curl --fail --silent --show-error \ -H "x-api-key: $TILDE_API_KEY" \ "$API_BASE/team/$TILDE_TEAM_ID/skill/$TILDE_SKILL_ID/package") PYTHON_PATH=$(printf '%s' "$MANIFEST" | \ jq -r '.files[] | select(.path == "examples/analyze.py") | .path') PYTHON_SHA256=$(printf '%s' "$MANIFEST" | \ jq -r '.files[] | select(.path == "examples/analyze.py") | .checksum_sha256') DOWNLOAD_URL=$(curl --fail --silent --show-error \ -X POST \ -H "x-api-key: $TILDE_API_KEY" \ -H "content-type: application/json" \ --data "$(jq -n --arg path "$PYTHON_PATH" '{path: $path}')" \ "$API_BASE/team/$TILDE_TEAM_ID/skill/$TILDE_SKILL_ID/package/download" | \ jq -r '.url') curl --fail --silent --show-error "$DOWNLOAD_URL" -o /tmp/analyze.py printf '%s %s\n' "$PYTHON_SHA256" /tmp/analyze.py | sha256sum --check sed -n '1,160p' /tmp/analyze.py python3 /tmp/analyze.py ``` Use `https://api.trytilde.ai/mcp`. Call `tilde_whoami` first. Skills and registries may be `team` or personal `user` resources; personal REST routes use `/api/v1/user/{user_id}/...` and have no team ID. Packages and registry memberships inherit their root owner, and a team registry cannot include a personal skill. Skills and registries each have independent visibility and ownership modes. Visibility governs list/get/search, package files, descriptions, and full skill reads. Ownership governs root settings, registry membership selection, mode/grant management, lifecycle, and deletion. An ownership grant or administrator role never supplies visibility. Use same-tenant user/group grants through the standard REST `/{id}/{plane}/grants` family; packages and registry-bound discovery tools inherit their root planes. ## Create a registry from team-owned skills 1. Call `tilde_create_skill` for each focused instruction document. Use a lowercase, hyphenated name, a concise discovery description, and complete Markdown content. 2. Call `tilde_list_skills` if you need to recover the created skill IDs. 3. Call `tilde_create_skill_registry` with a focused name, description, and `skill_ids`. 4. To change membership, call `tilde_update_skill_registry` with the complete desired `skill_ids` array. It replaces the current selection. 5. Call `tilde_list_skill_registries` to verify the registry and obtain its ID. A registry's private provider is created and enabled automatically. It exposes `list_skills`, `search_skills`, `read_skill_description`, and `read_skill`. ## Expose discovery to an agent 1. Call `tilde_search_enabled_capabilities` using the registry name. 2. Find the registry-bound provider and its four discovery functions. 3. Map each function to the agent's runtime MCP server with `tilde_set_mcp_server_tool_enabled`. 4. Verify the mappings with `tilde_search_enabled_capabilities`, filtered by `mcp_server_instance_id`. Tell the runtime agent to search summaries first, read one description, and load the full skill only when it is relevant. ## Inspect a registry from Global MCP * `tilde_list_skill_summaries`: list concise entries without full content. * `tilde_search_skill_registry`: semantically search one registry. * `tilde_read_skill_description`: inspect one candidate. * `tilde_read_skill`: load the complete content. Tilde SDK also exposes programmatic access through `context.skills` inside `chatKitEndpoint`. Use it when application code already knows the registry or skill to load. See the [human Skills guide](https://trytilde.ai/docs/skills). # State Source: https://trytilde.ai/docs/llms/state # Export and import Tilde state over Global MCP Tilde resource state is portable even though Tilde does not require Terraform. Keep `tilde.state.yaml` beside a custom agent so another workspace can reproduce its agents, ChatKit providers, tools, MCP servers, skills, wikis, memory bindings, reverse proxies, and relationships. State does not contain API keys, signing keys, provider credentials, conversation history, or memory content. Self-extension proposal state contains only secret-free intent, the server-authored preview, an optional secret-free setup continuation, and source receipts for audit. It excludes approval principals, Human Approval tokens, worker leases, runtime status, one-time outputs, and rollback authority. Import creates a new pending proposal with a new destination approval; it never imports an executed or approved state, and it never uses source receipts to delete destination resources. Portable resources use tagged `team`, `user`, or `user_team` ownership. Team export remains team-only by default. Personal and private-team resources require explicit inclusion and authorization, and import requires an `owner_mappings` entry from every source user ID to its target user ID. Missing mappings fail validation; never remove ownership or convert it to team ownership to make an import pass. Selected skills are exported as checksum-bound packages. Their `SKILL.md` entrypoint and package-local references, templates, scripts, examples, and media are embedded so import can verify and recreate the complete package without fetching mutable upstream content. Provider source and revision metadata remain attached as provenance. Curated hosted MCP connections export their stable catalog provider identity and declarative endpoint/authentication configuration. Dynamic OAuth client IDs, token endpoints discovered for that registration, access tokens, and refresh tokens are environment-specific and are not exported. On import, Tilde repeats discovery and dynamic client registration, then returns a one-time authorization URL. Manual OAuth configuration remains portable, while its user credential is reconnected through the normal pending-credential flow. Use `https://api.trytilde.ai/mcp`. Call `tilde_whoami`, select a workspace, and pass its `team_id` to every function below. ## Export 1. Call `tilde_export_state` with `format: "yaml"`. 2. Write the returned `state` string unchanged to `tilde.state.yaml`. 3. Review and commit the file with the agent source. For custom deployed agents, compare the state file and implementation with the [Hello World agent](https://github.com/trytilde/examples/tree/main/hello-world-agent), the [code review bot](https://github.com/trytilde/examples/tree/main/code-review-bot), and the rest of the [examples repository](https://github.com/trytilde/examples). Common providers such as Linq export as one `common_provider/installation` root plus a `credential/setup_item`. Generated Tool, ChatKit, Signal, and Reverse Proxy resources are common-owned aliases, not independent installations. Never place API tokens, webhook subscription IDs, or signing secrets in state. After import, complete the pending credential once so reconciliation restores the whole bundle. ## Import 1. Read the complete state file as text. 2. Call `tilde_validate_state` with `state`, `format: "yaml"`, and any declared string `variables`. Stop if `valid` is false. 3. Call `tilde_plan_state_import` with the identical state, format, and variables. 4. Show the plan to the user. Do not apply conflicts, destructive changes, or unexpected replacements without approval. 5. Call `tilde_import_state` only after the plan is approved. 6. Poll `tilde_get_state_import` with the returned `import_id` until the status is `applied`, `failed`, or `rolled_back`. 7. Capture generated outputs the first time an applied result returns them. Applied outputs are one-time secrets and are cleared from later summary reads. 8. Save any one-time OAuth authorization URL returned in the import outputs and send it to the user immediately. 9. Tell the user to complete any remaining pending credential setup in Tilde. Never call import as a substitute for plan. Use the same exact state and variables for validation, planning, and application. See the [human portable state guide](https://trytilde.ai/docs/terraform) for dashboard, CLI, multi-environment, and Deploy with Tilde workflows. # Tools Source: https://trytilde.ai/docs/llms/tools # Configure tools over Tilde Global MCP Use `https://api.trytilde.ai/mcp`. Call `tilde_whoami`. Team operations target a workspace; personal REST operations use `/api/v1/user/{user_id}/...` and infer the effective user for ordinary creates. Configured tool accounts and MCP servers support `team` or `user` ownership. Personal resources have no team ID. Runtime MCP servers use `user_tool_federation_mode: none | all | selected`, defaulting to `none`. Selected policies contain provider/tool-definition pairs only—not credentials, aliases, bound parameters, or user account IDs. At connection time Tilde authenticates and pins the effective user to the MCP session, then exposes the caller's active matching personal accounts under stable `user______` names. Tool groups, proxied/custom providers, MCP server instances, resource-server credentials, and user credentials have independent visibility and ownership modes. For tool and MCP roots, visibility governs discovery and permitted use; ownership governs settings, mappings, grants, and deletion. Credential visibility governs redacted metadata discovery only. Credential ownership or an exact consuming-resource capability governs brokering, rotation, deletion, and secret material. Private user/group grants never cross the root organization or team. An ownership grant or administrator role does not grant visibility. Credential list/get responses never include plaintext or decrypted values. Secret material is available only to ownership-authorized configuration flows or an exact bound consuming-resource capability. Never ask Global MCP to display, export, or relay a stored credential. Common-provider installations are live policy parents for the MCP tool group, ChatKit provider, signal provider, and reverse-proxy profiles generated from one provider setup. Their initial modes and grants come from the source resource-server credential, but later policy changes are made only through the installation's standard visibility/ownership APIs. Bound children cannot widen the parent. Credential rotation and secret administration remain separate. Cross-root use is an intersection: MCP invocation requires visibility of both the server and tool group (or its installation parent). Reverse-proxy invocation requires profile visibility and uses an internal exact credential-consumption capability; it does not require or confer credential ownership. ## Recommended workflow 1. Call `tilde_search_available_capabilities` with a specific intent such as `"GitHub pull request tools"`. Use `include_schemas: true` when you need provider or tool input details. Linq is a common provider: provisioning it from Tools or ChatKit creates the same credential-backed Tool, ChatKit, Signals, and Reverse Proxy bundle. Get the token from `https://dashboard.linqapp.com/api-tooling`. Tilde creates the managed webhook subscription; do not instruct users to add a second webhook unless they deliberately chose a standalone Signals provider. See `/guides/linq`. 2\. Configure the source: * Managed provider: `tilde_enable_toolkit_provider`. * Provider app that Tilde should provision: `tilde_auto_provision_toolkit_provider`. * Existing Streamable HTTP MCP server: `tilde_connect_proxied_mcp_server`. * Tilde SDK `toolEndpoint` backend: `tilde_register_custom_tool_backend`. 3. If the response contains `approval_url`, send it to the user. Immediately invoke the returned `next_tool_name` with `next_tool_arguments`. Do not continue until it returns `approved`. 4. Enable only the required provider functions with `tilde_set_toolkit_tool_enabled`. 5. Create a runtime server with `tilde_create_mcp_server`. Supply a stable lowercase `id`, a human-readable `name`, and `is_dynamic_tool_discovery: true` unless the toolset is very small and fixed. 6. Call `tilde_search_enabled_capabilities` to obtain the exact `tool_group_instance_id`, `tool_group_source_type_id`, and `tool_source_type_id` values. 7. Map each function with `tilde_set_mcp_server_tool_enabled`. 8. Call `tilde_search_enabled_capabilities` again, filtered by `mcp_server_instance_id`, to verify the final mapping. Do not confuse the global configuration MCP server with the runtime MCP server created in step 5. Static MCP mappings may reference workspace configured tools only. Personal configured tools are federation-only. Ownership-change endpoints never accept a different target owner. Personal-to-team promotion requires membership in the target team; narrowing a team resource requires team-or-higher administration and targets the effective user. Remove static mappings before narrowing an MCP server. For REST automation, use the standard `/{resource_id}/visibility`, `/{resource_id}/ownership`, and `/{resource_id}/{plane}/grants` operations described in OpenAPI. Use `principal_type: group` to share with a tenant-scoped Identity group. Child definitions and mappings inherit their root; do not try to grant them separately. ## Add a registered agent as an MCP tool Each ChatKit agent registration creates one credentialless `chatkit_agent_message` provider bound to that target agent. Use the returned `message_tool_provider_id`, or find the provider with `tilde_search_enabled_capabilities`, then map both provider functions onto an existing runtime MCP server: * `chatkit_agent_message_send` persists an inbound ChatKit message and immediately returns `ticket_id`, `session_id`, `next_tool`, and `next_arguments`. * `chatkit_agent_message_wait_for_response` subscribes to the live ChatKit session, emits streaming and queue-status MCP notifications, and returns the final persisted ChatKit message. The model-facing tool names may be customized on the MCP server; follow the returned `next_tool` instruction rather than guessing. Pass a prior `session_id` to continue the same child conversation. The target agent's `concurrency_policy` controls queueing, interruption, and batching. ## Managed providers Never guess provider IDs or credential source IDs. Take them from `tilde_search_available_capabilities`. Call `tilde_enable_toolkit_provider` with: * `team_id` * `tool_group_source_type_id` * `credential_source_type_id` * `display_name` * an existing credential ID only when the user supplied one Use `tilde_auto_provision_toolkit_provider` when search results advertise an auto-provisioned provider app. It requires the provider and app identifiers returned by search. ## Proxied MCP and custom HTTP tools Use `tilde_connect_proxied_mcp_server` for an existing Streamable HTTP MCP URL. Set its declared `auth_mode`; do not put secrets in names, URLs, or descriptions. Call `tilde_refresh_proxied_mcp_server` after the upstream tool catalog changes. For the server-authored hosted-provider catalog, direct the user to **Tools** → **Proxied MCP servers** → **Browse provider catalog**. Every published entry exposes reviewed tool definitions before credentials are supplied; providers without a validated snapshot are not published as connectable. Tilde records whether each snapshot is an exact public `tools/list` result or was inferred from official source or documentation; an authenticated `tools/list` response replaces the snapshot after connection. Do not ask the user to paste provider secrets into chat or into MCP arguments. OAuth client secrets, API keys, and bearer tokens must be entered through Tilde's credential setup. Dynamic OAuth client registrations are environment-specific and require authorization again after state import; pre-registered manual OAuth configurations remain declarative and their user credential is reconnected separately. Use `tilde_register_custom_tool_backend` for a signed discovery endpoint created with Tilde SDK `toolEndpoint`. Save the one-time signing key in the tool server, then call `tilde_refresh_custom_tool_backend` after its manifest changes. For implementation patterns, inspect the [code review bot](https://github.com/trytilde/examples/tree/main/code-review-bot) and the rest of the [examples repository](https://github.com/trytilde/examples). ## Reverse proxies Reverse proxies let application code call a provider's native API while Tilde injects its credential. Supported provider profiles are enabled by default. * Call `tilde_list_reverse_proxies` to find profile IDs and proxy base URLs. * Call `tilde_set_reverse_proxy_enabled` only when you need to change live traffic for a profile. ## Connect the deployed agent Pass the runtime MCP server ID to Tilde SDK `createMCPClient`. Follow the [human Tools guide](https://trytilde.ai/docs/tools) for the client code. The code review bot is the preferred reference for custom agents that combine MCP tools, local tools, and reverse proxies. Within a `chatKitEndpoint({ responseMode: "tool" })` handler, prefer `context.session.tools`, `context.$provider.tools`, or `context.session.createMCPClient({ serverId })`. These surfaces inject session-bound provider communication tools and prefill routing identifiers. `sendMessage` creates the visible ChatKit message; reactions, thread reads, and Linq poll operations are emitted as canonical tool-execution events. Use `context.mcp.connect({ serverId })` when a shared ChatKit agent should federate the verified speaker's eligible personal tools. The SDK forwards an invocation-scoped capability outside model input. Never serialize that capability, user IDs, account IDs, or credentials into messages, state, logs, or tool arguments. For an `agent_job` invocation, use the same `context.mcp.connect` surface. Tilde derives the human from the durable job's private parent-session lineage and an actual ancestor message with a server-authored human actor; do not insert a fake human message into the child session. Capabilities retain the child session, original trigger, and job ID/generation. Their use revalidates the running generation, private owner and grants, active participants, current team membership, and original external sender verification and channel policy. A resumed generation cannot reuse an older capability. Hidden continuations must also match their trusted AgentRun generation and worker lease. Personal federation is withheld if the lineage or original policy cannot be validated. ## Personal OAuth setup from an application Use the official SDK transport with the authenticated user's session. Discover provider/auth-method IDs from the team's provider-setup catalog, then call `POST /api/v1/team/{team_id}/provider-setup/start` with `personal: true`, `domain: "mcp"`, `provider_id`, `auth_method_id`, a unique `form_values.id`, optional `form_values.displayName`, and `return_url`. Follow the returned generic `next_action`. List the resulting accounts through the user-scoped tool-group route. Multiple accounts of the same provider remain distinct. Personal OAuth brokering is restricted to the effective owner; user credentials are encrypted and refreshed in the user scope. Omitting `personal` retains team setup. Personal credential setup ensures organization, workspace (when required for broker state), and user key defaults after validating the effective owner. Callbacks repair missing defaults before token exchange. A missing personal key must never be worked around by encrypting the user's tokens under a team key. # Memory Source: https://trytilde.ai/docs/memory Give your agents durable context through memory banks and structured wikis. Tilde provides two related ways to manage knowledge for agents. Memory banks and wikis can be workspace-owned or personal. Each root has independent visibility and ownership modes. Visibility controls listing, reading, recall, reflection, and other content use. Ownership controls configuration, source policy, schemas, grants, lifecycle, and deletion. A personal resource has no team ID, while a workspace resource remains in its team. Set either plane to **Team** or **Private**. Private access can be granted to an Identity user or group in the same tenant. Ownership and administrator authority do not reveal private memory or wiki content without visibility. Pages, revisions, assets, memories, generated tools, and lifecycle records inherit their bank or wiki root; they are not shared separately. Personal targets may read an accessible workspace source, but a workspace target cannot bind a personal source. Before removing someone from a workspace, Tilde requires durable personal projections and cross-workspace bindings to be detached or removed. Owners can promote a personal memory bank or wiki to a workspace they belong to. Workspace administrators may make one personal to themselves. Detach and purge source bindings or durable projections first so changing ownership cannot widen an existing audience. | Resource | Use it for | Agent access | | --------------- | ---------------------------------------------------------------------------------------------- | ----------------------------------------------------------- | | **Memory bank** | Durable facts, decisions, preferences, and work summaries that agents can recall semantically. | `retain`, `recall`, `reflect`, and `delete_document` tools. | | **Wiki** | Agent-maintained Markdown pages, revisions, relationships, graph queries, and media assets. | Page, schema, relationship, graph, and asset tools. | Use memory banks when an agent needs relevant context without knowing where it was stored. Use wikis when the knowledge should have an explicit structure that people and agents can browse and maintain. ## Memory banks A memory bank is an isolated store that lasts beyond one conversation. Agents can retain stable documents, recall content relevant to a query, and reflect on the bank to produce a contextual answer. Tilde memory banks use a managed Helix graph and vector store. Tenant and bank predicates isolate every node, edge, search, and mutation. Recall combines semantic, lexical, exact-title, and graph candidates before reranking a bounded result set with evidence and source provenance. Bank access is resolved in Postgres before a scoped provider query is created, so agents never submit a tenant or bank partition directly. Owners can also import and export portable bank templates for supported configuration, mental models, and directives. Each retained document has typed fields for its OKF category, title, importance, authorship, overwrite policy, evidence, subjects, supersession, source, and learning agent. The optional `metadata` object is only for provider-native or application-specific extension facts. It does not affect access, ranking, graph links, provenance, or synthesis. Open Tilde, select your workspace, and go to **Memory** → **Memory Banks**. Click **New memory bank**, choose **Personal** or **Workspace**, then give the bank a clear name and description. Personal banks follow you across agents without becoming visible to the workspace. Tilde automatically creates a private tool provider bound to the bank and enables these tools: * `retain` stores or replaces a stable document. Reuse its `document_id` when updating it. Select an OKF `memory_type`, set `importance` from `0.0` to `1.0`, and use typed relations for evidence, subjects, or supersession. * `recall` searches for memories relevant to a query. * `reflect` answers a question using knowledge held by the bank. * `delete_document` removes a retained document by ID. Tilde binds the bank ID internally, so it does not appear as an agent-controlled tool parameter. ### Recall memory for the effective speaker ChatKit automatic memory is opt-in. An agent or channel stores one `automatic_memory_mode`: `none`, `personal`, `personal_plus_agent`, or `team`. `none` is the default. `memory_bank_ids` independently selects the banks that ingest conversations involving that resource. The recipient agent calls `/chatkit/agents/{agent_id}/sessions/{session_id}/automatic-memory/recall` with a durable `message_id` and optional `max_tokens`. Tilde derives the effective speaker from that stored message and session, applies bank visibility, and returns a bounded projection with provenance. The caller cannot choose another user or use a hidden continuation as someone else's memory context. ### Synthesize personal memory in the background A personal bank can assign a synthesizer with `synthesizer_agent_id` and `synthesizer_team_id`. Tilde creates one stable private ChatKit synthesis session for that bank and queues visible completed-turn evidence. Streaming deltas, hidden continuations, and the synthesis session itself do not recursively enqueue more work. The synthesis agent receives bank-bound `recall`, `retain`, and document-deletion operations under `/memory/synthesis-sessions/{session_id}`. Every mutation and completion receipt must carry the current claim's batch ID, complete evidence-ID set, and fresh lease owner. This prevents a stale worker from adopting another claim's mutation or completion. Clearing a personal bank's synthesizer stops background processing but preserves queued evidence for a later assignment. OpenBot's automatic-memory wiring is shipped and defaults to `none`. Owners opt in with `OPENBOT_AUTOMATIC_MEMORY_MODE` or an `AGENT__AUTOMATIC_MEMORY_MODE` override. `personal_plus_agent` provisions a lifecycle-owned agent bank; `personal` and `team` select recall without creating that bank. Memory Catcher inherits the installation's selected Codex, direct Gateway, or managed-OIDC inference provider and owns no bank, preventing recursive synthesis. OpenBot declares the owned bank's synthesizer through the Agent Resource Bundle field `memory.bank.synthesizer_agent_id`. It is a stable same-team ChatKit agent key. Supplying `memory-catcher` validates and converges that assignment on creation, update, and portable state import. Omitting the field preserves the bank's current or server-default assignment. Setting `memory.bank.enabled` to `false` deletes the lifecycle-owned bank. Before inference, Memory Catcher validates the prompt's batch digest, exact ordered evidence-ID sequence, and worker lease through `/memory/synthesis-sessions/{session_id}/validate-batch`. Tilde accepts only the current prompt-sized evidence chunk under that unexpired lease. Every later mutation repeats the same typed binding, so a stale worker, reordered set, or arbitrary subset cannot authorize a mutation or completion. ### Account for managed inference with AI credits Agent-authenticated hosted runtimes can reserve organization AI credits before a model call, then commit the exact provider receipt. Reserve with `estimated_cost_microusd` and an `idempotency_key`. Commit with `reservation_id`, `actual_cost_microusd`, `model_id`, input/output token counts, tags, and a second idempotency key. Release an unused reservation explicitly. Human-authenticated top-ups are separate from agent spend. OpenBot now applies this lifecycle to every model call made through Tilde-managed Vercel project OIDC, including Memory Catcher synthesis. It writes AgentRun effect intent before the provider starts, records the Gateway generation for recovery, and settles the authoritative receipt before reporting hosted cost to the run. Direct owner Gateway keys and Codex subscription inference are outside this managed meter. Every Gateway call reserves credits first, including BYOK. Vercel can fall back from BYOK to charged system credentials, so BYOK cannot safely bypass preflight. When the authoritative generation receipt reports BYOK, OpenBot releases the reservation. A system or fallback receipt is committed. An organization with no Tilde AI credits cannot start a Gateway call even when BYOK is configured. See [Vercel's BYOK behavior](https://vercel.com/docs/ai-gateway/authentication-and-byok/byok). OpenBot never repeats a planned, uncertain, or reconciled provider call automatically. If the model response cannot be recovered, it fails that AgentRun safely; a later owner message creates a new run. Hosted `max_cost_microusd` uses authoritative receipt cost after each call and can overshoot by the final call, while organization credit reservation remains a pre-call gate. Non-hosted cost budgets still require configured input and output price rates. ## Wikis A wiki is a structured Markdown knowledge base for you personally or for your team. It can contain nested pages, typed data, version history, semantic relationships, graph queries, and media assets. Go to **Memory** → **Wikis** and click **New wiki**. Choose **Personal** or **Workspace**, then select memory banks with the same ownership scope. Tilde synchronizes Wiki changes into those banks, giving agents both structured Wiki access and semantic recall over the same knowledge. Creating a wiki automatically provisions and enables its private wiki tools. They cover: * **Pages:** list, read, create or update, move, delete, migrate, inspect history, and run bounded literal or regular-expression grep with paths, line numbers, and context. * **Data model:** manage versioned page types, JSON schemas, and relationship types. * **Graph:** relate pages, inspect backlinks and neighborhoods, and traverse relationships. * **Assets:** upload, download, update, delete, and inspect media references. Each tool is bound to the wiki that created it, so an agent cannot redirect a call to another wiki by changing an input parameter. ### Wiki schema packs A Wiki Schema Pack adds a coherent data model to a wiki. Each pack contains page types with JSON schemas and the semantic relationships allowed between them. Go to **Memory** → **Wiki Schema Packs**, choose a pack, and select its destination wiki. Tilde preserves definitions with matching stable keys. Installed definitions remain editable and versioned inside the wiki. Schema packs do not create a separate tool provider. The wiki's existing tools immediately work with the added page types and relationships. ## Keep memory continuously updated Use automatic ingestion for source data, agent tools for deliberate updates, and bank-sharded background synthesis for durable lessons from conversations. ### Ingest supported sources automatically Open a memory bank and select the sources you want it to ingest. Tilde can ingest ChatKit conversations, signals, wikis, skills, and MCP servers. Personal banks initially accept personal Signal providers and personal Wikis; workspace banks accept workspace sources. Once a source is linked, Tilde backfills it, detects changes, and resynchronizes affected documents into the bank. A source is not shared with every memory bank automatically. You explicitly choose which banks receive it when configuring the connection, Wiki, or bank. A personal source can bind only to a personal bank owned by the same user and organization. ### Let an agent maintain its knowledge Give an agent the `retain` tool so it can write directly to its memory bank. Ask it to use a stable `document_id` for knowledge that should be updated instead of duplicated. Give the agent wiki page and relationship tools when it needs to maintain structured knowledge. If the wiki is linked to the agent's memory bank, each wiki update is ingested into that bank automatically. The agent can then use semantic recall over the content without writing the same information with `retain`. Treat the wiki as a first-class source of truth for common and relational data such as customers, projects, ownership, policies, and dependencies. Use the memory bank for semantic recall, conclusions, preferences, and concise summaries that do not belong in a structured page. ### Use background synthesis Assign a synthesizer agent when you create or configure a bank. Tilde shards evidence by bank and starts the assigned agent when the pending queue reaches 1,000 estimated tokens. One synthesizer can serve many banks, but each invocation receives tools bound to exactly one bank and one active evidence lease. A bank without an assigned synthesizer continues collecting evidence until you configure one. The synthesizer recalls related facts, writes or supersedes typed memories, and records a cited no-op when the evidence adds nothing durable. Owner-written explicit facts are protected from automatic overwrite and deletion. Mutation and completion receipts are operational records; they are not retained memories or exported configuration. You can also run a foreground agent when you need immediate synthesis. Its memory tools use the same typed document contract, while its normal conversation remains responsible for user-visible communication. ```text Memory synthesis guidance theme={"system"} Review the supplied evidence batch. Identify durable facts, decisions, preferences, outcomes, and unresolved work. Ignore greetings, repeated context, temporary instructions, and unverified claims. Update structured and relational facts in the wiki first. Use stable page identifiers and preserve existing relationships. Retain concise summaries that do not belong in the wiki in the memory bank. Recall related memories before writing, and reuse stable document IDs when updating them. Do not retain secrets or duplicate content already ingested from the wiki. ``` This pattern keeps raw event noise out of long-term memory while steadily improving the context available to future sessions. ## Expose memory tools to an agent Memory bank and wiki tools are enabled automatically when you create their resource. You do not need to configure another provider or supply credentials. Go to **Tools** → **Manage Enabled Tools**. Find the provider named for your memory bank or wiki and review its enabled tools. Keep destructive tools such as `delete_document`, `delete_page`, and schema deletion out of the agent's MCP server unless it needs them. Go to **Tools** → **MCP Servers** and open the server used by your agent. Add the memory bank or wiki tools you want to expose. Enable dynamic mode when you add the full wiki toolset. It lets the agent search for the relevant tool instead of loading every wiki tool schema into its context at once. Connect to that MCP server with the Tilde SDK. Memory and wiki tools are returned alongside its other tools. ```typescript wherever-you-run-your-agent.ts theme={"system"} import { openai } from "@ai-sdk/openai"; import { generateText } from "ai"; import { createMCPClient } from "@trytilde/sdk-vercel-ai-node"; const { mcp, closeMcp } = await createMCPClient({ client: tilde, serverId: process.env.TILDE_MCP_SERVER_ID!, }); try { await generateText({ model: openai("gpt-5.5"), messages, tools: await mcp.tools(), }); } finally { await closeMcp(); } ``` See [Tools](/docs/tools) for the complete client and environment setup. ## Guide the agent Tell the agent which knowledge belongs in each resource. ```text Agent instruction theme={"system"} Recall relevant memory before starting work that may depend on past decisions. Retain durable facts, decisions, and concise work summaries. Use the wiki for structured knowledge that should be browsed, linked, or maintained. Follow the wiki's page schemas and relationships when creating or updating pages. Do not store secrets, temporary instructions, or unverified assumptions. ``` ## Memory and ChatKit history ChatKit history reconstructs one conversation. Memory banks and wikis carry selected knowledge across sessions, channels, and agents. Do not copy every message into memory. Keep the part another session would need: the decision, its context, and the resulting state. # Quickstart Source: https://trytilde.ai/docs/quickstart Build, run, and test your first Tilde agent. Building chat directly into your own frontend? Follow [Frontend chat with your own authentication](/docs/guides/frontend-chat) to set up identities, an organization proxy token, and a same-origin streaming proxy. Tilde is designed for agents to build more agents. Choose **Agentic workflow** to work through your coding agent, or **For humans** to follow the same steps yourself. This guide shows you how to build and test a signed ChatKit endpoint using Next.js and the Vercel AI SDK. A completed [Hello World agent](https://github.com/trytilde/examples/tree/main/hello-world-agent) is available for reference. Connect the client where your coding agent runs to Tilde's global MCP server. Choose your client and complete its setup. Send this prompt to the connected agent. Start by reading [https://trytilde.ai/llms.txt](https://trytilde.ai/llms.txt) and use [https://trytilde.ai/docs/llms.txt](https://trytilde.ai/docs/llms.txt) to open the production-hosted agent guides. Use [https://github.com/trytilde/examples/tree/main/hello-world-agent](https://github.com/trytilde/examples/tree/main/hello-world-agent) only as a reference and create the app and files in my project. Explain the route before changing it, then ask what I want my agent to do. Keep Tilde webhook verification, ChatKit history, and server-side secrets intact. Register the local endpoint at /api/hello-world as a ChatKit agent, save the returned Tilde API key and webhook signing key in .env.local, sign in with `tilde auth login`, run the app through a Tilde Dev Tunnel, and test it in ChatKit workspace. Any project that includes a `tilde.state.yaml` file is instantly deployable to your Tilde account. Use the Deploy with Tilde button in a project's `README.md`, or import the file manually. See [Terraform](/docs/terraform) to learn more. You need Node.js 22 or newer, pnpm 10, a Tilde account, and an OpenAI API key. ```bash theme={"system"} pnpm create next-app@16.2.12 hello-world-agent --ts --eslint --app --no-src-dir --no-tailwind --use-pnpm cd hello-world-agent pnpm add @ai-sdk/openai ai @trytilde/sdk @trytilde/sdk-vercel-ai-node pnpm add -D openbot touch .env.local ``` Create `app/api/hello-world/route.ts`. You can compare it with the [completed route](https://github.com/trytilde/examples/blob/main/hello-world-agent/app/api/hello-world/route.ts) in the examples repository. ```typescript app/api/hello-world/route.ts theme={"system"} import { openai } from "@ai-sdk/openai"; import { chatKitEndpoint, convertToAiSdkMessages, createClient, } from "@trytilde/sdk-vercel-ai-node"; import { consumeStream, convertToModelMessages, streamText, } from "ai"; export const POST = chatKitEndpoint({ client: createClient({ apiKey: process.env.TILDE_API_KEY!, orgId: process.env.TILDE_ORG_ID!, teamId: process.env.TILDE_TEAM_ID!, }), webhookSigningKey: process.env.TILDE_WEBHOOK_SIGNING_KEY!, async handler(request, context) { const history = await context.session.history(); const messages = await convertToAiSdkMessages({ messages: [...history.items, ...context.messages], chatkit: context.chatkit, }); const result = streamText({ abortSignal: request.signal, messages: await convertToModelMessages(messages), model: openai("gpt-5.5"), system: "You are a helpful assistant. Keep your answers concise.", }); return result.toUIMessageStreamResponse({ consumeSseStream: consumeStream, originalMessages: messages, }); }, }); ``` Change the `system` instruction to change what your agent does. Keep the signed `chatKitEndpoint` wrapper and ChatKit history conversion. 1. Open Tilde, select your workspace, and go to **ChatKit** → **Agents**. 2. Click **Register agent** and name it `Hello World`. 3. Enable **Local running endpoint** and enter `api/hello-world` as the endpoint path. 4. Click **Register**, then copy the one-time API key and webhook signing key. Set these values in `.env.local`. Find the organization and team IDs under **Settings** → **Team settings** → **General information**. ```dotenv .env.local theme={"system"} TILDE_API_KEY= TILDE_ORG_ID= TILDE_TEAM_ID= TILDE_WEBHOOK_SIGNING_KEY= ``` Sign in to Tilde before opening the tunnel. The login flow asks you to select the workspace containing **Hello World**. Then start your app's development process through the tunnel. Replace `pnpm dev` with the command you normally use to run your app locally. The tunnel gives your local agent a public HTTPS endpoint, allowing Tilde to deliver messages, webhooks, and tool invocations while you develop. For ChatKit, `chatKitEndpoint` verifies Tilde's webhook signature and rejects requests without a valid signature. ```bash theme={"system"} pnpm exec openbot auth login pnpm exec openbot tunnel -- pnpm dev ``` The Dev Tunnel exposes every page and API route served by your local app—not only the agent endpoint—to the public internet. Disable any unneeded or unsecured routes before starting the tunnel, or protect them with authentication and use the tunnel with caution. Open [**ChatKit workspace**](https://api.trytilde.ai/chatkit-workspace), select the workspace where you registered **Hello World**, start a session with the agent, and send: ```text theme={"system"} Say hello in one sentence. ``` ## Continue exploring
# Skills Source: https://trytilde.ai/docs/skills Give agents reusable instructions that load only when needed. A skill is a focused set of instructions for a job. A skill registry groups related skills so an agent can discover short summaries first and load the full instructions only when needed. Skills and registries can be workspace-owned or personal. Each has independent visibility and ownership modes. Visibility controls discovery, package inspection, and reading skill content. Ownership controls root settings, registry membership, grants, and deletion. Set a plane to **Private** and grant a same-tenant Identity user or group when sharing should be narrower than the workspace. Ownership and administrator access do not imply visibility. Packages inherit their skill, while registry discovery tools and membership views inherit the registry. A personal registry may include personal skills owned by that same user, while a workspace registry cannot widen access by including a personal skill. Tilde synchronizes trusted upstream skill providers from official GitHub repositories. The built-in sources include Cursor's first-party plugins and canvases, Notion, Granola, Parallel, Superpowers, Browserbase, Apollo, Zoom, Stripe, Neon, Vercel, AWS, Anthropic, Microsoft, Cloudflare, and YC Software QM's portable general-purpose design skills where those projects publish valid `SKILL.md` files. Monorepo sources are path-scoped so unrelated third-party plugins and QM runtime-specific skills are not imported. Each synchronization is tied to an upstream commit. Tilde stores the complete bounded skill package, not only `SKILL.md`: package-local references, templates, scripts, examples, and media are retained with their relative paths and media types. Unsafe paths and symbolic links are rejected, and a partial upstream fetch never replaces the previous successful snapshot. Skills removed or renamed upstream are removed from the provider catalog on the next complete sync, while team-owned copies and registry membership remain explicit Tilde resources. Portable state embeds the selected package files with content checksums. Import verifies every file before recreating the package in the target workspace, so referenced assets remain available without relying on the original provider being reachable during import. ## Use package assets Call `GET /api/v1/team/{team_id}/skill/{skill_id}/package` to inspect the immutable package manifest and its entrypoint, paths, media types, sizes, checksums, executable flags, and Git provenance. To retrieve one referenced file, call `POST /api/v1/team/{team_id}/skill/{skill_id}/package/download` with its exact manifest `path`. Tilde returns a short-lived download URL; use the manifest checksum when persisting or executing downloaded content. For example, suppose the manifest lists a Python helper at `examples/analyze.py`: ```bash theme={"system"} API_BASE="https://api.trytilde.ai/api/v1" MANIFEST=$(curl --fail --silent --show-error \ -H "x-api-key: $TILDE_API_KEY" \ "$API_BASE/team/$TILDE_TEAM_ID/skill/$TILDE_SKILL_ID/package") PYTHON_PATH=$(printf '%s' "$MANIFEST" | \ jq -r '.files[] | select(.path == "examples/analyze.py") | .path') PYTHON_SHA256=$(printf '%s' "$MANIFEST" | \ jq -r '.files[] | select(.path == "examples/analyze.py") | .checksum_sha256') DOWNLOAD_URL=$(curl --fail --silent --show-error \ -X POST \ -H "x-api-key: $TILDE_API_KEY" \ -H "content-type: application/json" \ --data "$(jq -n --arg path "$PYTHON_PATH" '{path: $path}')" \ "$API_BASE/team/$TILDE_TEAM_ID/skill/$TILDE_SKILL_ID/package/download" | \ jq -r '.url') curl --fail --silent --show-error "$DOWNLOAD_URL" -o /tmp/analyze.py printf '%s %s\n' "$PYTHON_SHA256" /tmp/analyze.py | sha256sum --check sed -n '1,160p' /tmp/analyze.py python3 /tmp/analyze.py ``` Set `TILDE_TEAM_ID` and `TILDE_SKILL_ID` to the workspace and skill identifiers. The first request reads the manifest, the second asks Tilde for a short-lived URL for that exact file, and the final commands inspect and run the downloaded example. ## Create a skill registry Open Tilde, select your workspace, and go to **Skills** → **Registries**. Create a registry with a clear name and description. Add trusted upstream skills from a configured provider or create a team-owned skill. Keep each registry focused on one agent or workflow. When you create a registry, Tilde also creates and enables a private tool provider bound to it. Go to **Tools** → **Manage Enabled Tools** and find the provider named after your registry. It exposes four tools: * `list_skills` lists the skills in the registry. * `search_skills` returns relevant skill summaries. * `read_skill_description` reads one description before loading its instructions. * `read_skill` loads the complete skill. Go to **Tools** → **MCP Servers** and open the server used by your agent. Add the registry's four discovery tools. Tell the agent to search first, inspect the description, and read the complete skill only when it is relevant. This keeps large instruction files out of its context until they are useful. ## Access skills programmatically Every signed `chatKitEndpoint` handler receives a typed `context.skills` client. Use it when your application already knows which registry and skill to load. Use the MCP discovery tools when the model should choose a skill itself. ```typescript app/api/agent/route.ts theme={"system"} import { openai } from "@ai-sdk/openai"; import { chatKitEndpoint, convertToAiSdkMessages, createClient, } from "@trytilde/sdk-vercel-ai-node"; import { consumeStream, convertToModelMessages, streamText } from "ai"; const tilde = createClient({ apiKey: process.env.TILDE_API_KEY!, orgId: process.env.TILDE_ORG_ID!, teamId: process.env.TILDE_TEAM_ID!, }); export const POST = chatKitEndpoint({ client: tilde, webhookSigningKey: process.env.TILDE_WEBHOOK_SIGNING_KEY!, async handler(request, context) { const registry = await context.skills.registry( process.env.TILDE_SKILL_REGISTRY_ID!, ); const availableSkills = await registry.list(); const skill = await registry.find("pull-request-review"); console.log(availableSkills.map(({ name, description }) => ({ name, description }))); const history = await context.session.history(); const messages = await convertToAiSdkMessages({ messages: [...history.items, ...context.messages], chatkit: context.chatkit, }); const result = streamText({ abortSignal: request.signal, messages: await convertToModelMessages(messages), model: openai("gpt-5.5"), system: skill.content, }); return result.toUIMessageStreamResponse({ consumeSseStream: consumeStream, originalMessages: messages, }); }, }); ``` Set `TILDE_SKILL_REGISTRY_ID` to the registry ID shown in Tilde. `registry.find()` accepts a skill ID or its stable name. # Terraform Source: https://trytilde.ai/docs/terraform Export, share, and reproduce portable Tilde resource state. Well, not exactly. Tilde does not require a Terraform provider, but all Tilde resource state is portable. This makes it easy to share a setup and reproduce it across development, staging, and production workspaces. ## The `tilde.state.yaml` file `tilde.state.yaml` describes the desired configuration for resources in a workspace. It can include ChatKit agents and providers, MCP servers, tool providers, skill registries, wikis, memory-bank bindings, reverse proxies, and their relationships. State files can declare variables for values that change between environments, such as an agent endpoint URL. They do not contain API keys, signing keys, third-party credentials, conversation history, or other runtime content. An import returns generated values separately and leaves credential-backed resources pending until you connect the corresponding accounts. Each exported resource may carry a tagged `team`, `user`, or `user_team` ownership value. Workspace export remains workspace-only unless personal or private resources are explicitly included. When importing personal or `user_team` resources, provide an explicit source-user-to-target-user mapping. Import fails if an owner is unmapped; it never silently promotes a personal resource to workspace ownership or creates an orphan. Hosted MCP provider connections preserve their catalog provider identity, endpoint configuration, authentication mode, tool provider, and MCP mappings. API keys, bearer tokens, OAuth client secrets, access tokens, and refresh tokens remain encrypted credential references rather than state values. Safe self-extension proposals export secret-free intent, the server-authored review preview, any secret-free provider-setup continuation, and source resource receipts as audit metadata. Approval identity, Human Approval tokens, leases, execution status, generated outputs, and source rollback authority are not portable. Import always creates a fresh pending proposal in the destination workspace, rebuilds its preview, and requires a new explicit human approval there. Imported source receipts never authorize deletion of destination resources. OAuth providers that use dynamic client registration must register a new client in the destination environment because the redirect URI and client registration belong to the source environment. Import recreates the provider and returns a one-time authorization URL. Manual OAuth providers keep their pre-registered client configuration and ask you to reconnect the user credential separately. Commit `tilde.state.yaml` with your application so reviewers can see which Tilde resources it expects. ## Export state from a workspace 1. Select the workspace you want to export. 2. Go to **Settings** → **Team settings** → **State**. 3. Open the **Export** tab and click **Export**. Tilde downloads the workspace configuration as `tilde.state.yaml`. ```bash theme={"system"} pnpm add -D openbot pnpm exec openbot auth login pnpm exec openbot state export ./tilde.state.yaml ``` ## Import state manually 1. Select the destination workspace. 2. Go to **Settings** → **Team settings** → **State**. 3. Open the **Import** tab and upload `tilde.state.yaml`. 4. Provide any variables requested by the file. 5. Review the validation result and resource plan, then apply it. 6. Save the generated import outputs and complete any items under **Pending credentials**. You can perform the same workflow from the CLI: ```bash theme={"system"} pnpm exec openbot auth login pnpm exec openbot state import ./tilde.state.yaml ./tilde-state-import-outputs.yaml ``` The CLI shows the plan before applying it. Add `--auto-apply` only in a trusted automated workflow where the state change has already been reviewed. ## Add a Deploy with Tilde button Add the button to a project's `README.md` when its repository contains a `tilde.state.yaml` file. [![Deploy with Tilde](https://api.trytilde.ai/deploy-button.svg)](https://api.trytilde.ai/deploy?repository-url=https%3A%2F%2Fgithub.com%2Ftrytilde%2Fexamples\&state-path=hello-world-agent%2Ftilde.state.yaml) Clicking the button opens Tilde, asks the user to select a workspace, reads the state file from GitHub, collects its variables, and shows the import plan before creating resources. Common-provider integrations are exported as one installation plus a pending credential setup reference. For example, importing Linq restores the desired Tool, ChatKit, Signals, and Reverse Proxy bundle without exporting its API token or webhook signing secret. Reconnect the Linq credential once after import to materialize every generated surface. Use this Markdown and replace both query parameters with your repository and state-file path: ```markdown README.md theme={"system"} [![Deploy with Tilde](https://api.trytilde.ai/deploy-button.svg)](https://api.trytilde.ai/deploy?repository-url=https%3A%2F%2Fgithub.com%2FYOUR_ORG%2FYOUR_REPOSITORY&state-path=tilde.state.yaml) ``` `repository-url` must point to a GitHub repository over HTTPS. `state-path` must be a relative path to a YAML file, so monorepos can use a value such as `agents/code-review/tilde.state.yaml`. ## Manage multiple environments Keep one reviewed state file as the shared baseline. Use variables for environment-specific endpoints and reconnect credentials separately in each workspace. Import the same state into development, staging, and production, then review each plan before applying it. State imports can update or replace existing configuration. Review conflicts, destructive changes, requested variables, and pending credentials before applying a plan. # AgentMail tools for AI agents Source: https://trytilde.ai/docs/tool-providers/agentmail Explore 2 AgentMail tools for AI agents in Tilde, including supported authentication and MCP capabilities. Compose and reply to AgentMail email conversations. Tilde exposes **2 AgentMail tools** for AI agents through MCP. Connect with AgentMail API key. ## Popular AgentMail tools * **sendMessage** — Compose or reply to an email through a bound AgentMail inbox. * **getThread** — Get the AgentMail thread bound to this ChatKit session. ## Connect AgentMail to an AI agent Add AgentMail from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # AWS tools for AI agents Source: https://trytilde.ai/docs/tool-providers/aws Explore 9 AWS tools for AI agents in Tilde, including supported authentication and MCP capabilities. AWS cloud operations, regional availability, documentation, skills, file transfer, and sandboxed multi-step API execution through the official AWS MCP Server. Requests are authenticated with encrypted AWS IAM credentials and SigV4. Tilde exposes **9 AWS tools** for AI agents through MCP. Connect with AWS IAM credentials. ## Popular AWS tools * **call aws** — DEPRECATED: This tool is being deprecated in favor of `run_script`. Use `run_script` instead. Execute AWS CLI commands. PRIMARY tool when you know the exact command needed. - Command MUST start with "aws" and follow AWS CLI syntax - For cross-region operations, include --region; for alternate profiles, include --profile - max\_results defaults to 100 for paginated operations. Larger values consume more tokens. OMIT for non-paginated ops (get, create, delete). PAGINATION: If response has non-null "pagination\_token", results are INCOMPLETE. Call again with "--starting-token \". ALWAYS paginate through ALL pages before reporting counts or conclusions. MULTI-STEP PATTERNS: Most tasks require list→describe workflows. List operations return only identifiers—always follow with describe/get calls for full details. Never infer from names alone; retrieve and inspect actual data. MULTI-REGION/PROFILE: When a task involves "all regions" or multiple profiles, query EVERY relevant region/profile separately. LOCAL FILE SYSTEM: No filesystem access. Use '-' for output file args. No 'file://'/'fileb://'—provide values inline. S3-to-S3 operations (both source and destination are S3 URIs) ARE supported. Command restrictions: NO pipes, shell operators, grep/awk/sed, redirection, command substitution, shell variables, or local file paths. BACKGROUND TASKS: Long-running operations return \{task\_id, status:"working"}. Poll via `get_tasks` tool with task\_ids=\[...]—NOT an aws subcommand. Each task runs once. FILE UPLOAD: Ask user for a staging bucket. Get pre-signed URL via get\_presigned\_url, upload file, then call call\_aws with staging\_sources (bucket, key, cli\_argument, optional extract). Do NOT include cli\_argument flags in cli\_command. For directories: zip first (zip-only, max 4GB), use extract:true. For commands with native S3 args (--code S3Bucket=X,S3Key=Y), use those directly—no staging needed. Examples: - aws s3api put-object --bucket my-bucket --key data.bin with staging\_sources=\[\{"bucket":"staging","key":"data.bin","cli\_argument":"--body"}] - aws lambda create-function --function-name F --runtime python3.12 --handler index.handler --role \ with staging\_sources=\[\{"bucket":"staging","key":"func.zip","cli\_argument":"--zip-file"}] * **get presigned url** — Generate pre-signed S3 URLs for uploading or downloading files. Use BEFORE call\_aws when a command requires a local file path. Use for direct S3 uploads/downloads instead of call\_aws. Max upload 5 GB; larger files use multipart via call\_aws. For uploads: generates PUT URL. For downloads: generates GET URL. No special headers needed unless s3\_params provided—then corresponding HTTP headers MUST be included or request fails with SignatureDoesNotMatch. * **get tasks** — Poll status of long-running tasks. Use after a tool call returns task\_id with status "working". Up to 3 IDs per call. Tasks expire after 5 min. Pass poll\_iteration (start at 1, increment each call) and follow the recommended\_wait\_seconds in the response before polling again. * **run script** — Execute Python code in a sandboxed environment with AWS API access via `call_boto3`. Top-level `await` supported. No network access except `call_boto3`. The response includes an `api_calls` list summarizing the AWS API calls the script issued (one entry per call: `{service, operation, status, n_items?, error?}`). Use it to verify which APIs ran, in what order, and that no expected step was silently skipped or swallowed by `return_exceptions=True` before trusting `return_value`. `python async def call_boto3( *, # only keyword arguments service_name: str, # aws service name, e.g. s3 operation_name: str, # API operation name, e.g. ListBuckets region_name: str | None = None, # Optional. default to the user configured region params: dict | None = None, # Optional. parameters to call the API, default to empty ) -> dict: # returns json dict, datetimes as ISO strings ... ` ⚠️ FORBIDDEN: `getattr`, `__class__`, `__dict__`, `__subclasses__`, `import boto3`, subprocess, HTTP/socket calls. Use `isinstance()`/`hasattr()` instead. ⚠️ USE run\_script FOR: - 2+ API calls: listing, filtering, counting, parallel calls, multi-step, multi-region - ANY analysis or comparison: configs, policies, tags, properties across resources - Permission checks: gather identity, resource, and trust policies in one script - Streaming APIs (live-tail, subscribe-to-shard) - results auto-capped; inform user if partial. ⚠️ ONE SCRIPT PER TASK: Do NOT split work across multiple run\_script calls. If answering the question requires fetching IDs then describing each - do both in one script. Returning intermediate data to "decide the next step" wastes round-trips and inflates the context. Plan the full logic before writing the script. ⚠️ LIST→DESCRIBE IS MANDATORY: List APIs return ONLY names/ARNs. To check ANY attribute: 1. List\* → get ALL names 2. Get\*/Describe\* PER RESOURCE for the attribute 3. Feature-specific APIs are SEPARATE: streams, encryption, lifecycle, metrics often have dedicated Get\* APIs NOT in the main Describe. 4. ResourceNotFoundException = "not configured"-valid data, don't skip ⚠️ CONTENTS vs CONTAINER: "empty buckets" → list objects IN bucket. "records in table" → scan. "X configured" → Get*Configuration API. ⚠️ NEVER TRUNCATE: Check ALL resources. Never `\[:10\]` or `\[:50\]`. Missing resource = wrong answer. ⚠️ DISTRUST EMPTY RESULTS: Before reporting "0 found" verify the response had expected keys and no exceptions occurred. If uncertain → "unable to verify" NOT "0 found". RULES: 1. SELF-CONTAINED: Never paste resource names/ARNs from prior results into code. Discover everything inside the script. 2. OUTPUT: `result = {...}` then `result` alone on the last line. Never use `print()`. 3. CONCURRENCY: Use `asyncio.gather(*\[...\])` for parallel calls. Use `return_exceptions=True` only for read APIs (Describe*, List\*, Get\*). For mutation APIs (Put\*, Create\*, Delete\*, Update\*), let exceptions propagate immediately. 4. REGIONS: The user's default region is used when region\_name is not specified. For all-regions: DescribeRegions, iterate ALL. 5. PAGINATION: List/Describe APIs are auto-paginated - do NOT pass limit parameters or loop over tokens manually. Just call the API and all results are returned. Auto-pagination is bypassed only when you explicitly pass the limit key (e.g. `MaxResults`, `Limit`, `MaxItems`) - avoid doing this unless you intentionally want a page. 6. PERMISSIONS: Gather ALL policies in ONE script (identity, resource, trust). ARN `bucket` ≠ `bucket/*`. Report YES, PARTIAL, or NO with reasoning. 7. VERIFY API RESPONSE: Confirm the operation returns the field you need. 8. NO COMMENTS: Do not write any comments in the code. 9. FETCH VS JUDGE: Use the script to fetch and structure data. For mechanical tasks (count, filter by exact value, aggregate) encode the logic in the script. For tasks requiring judgment ("misconfigured", "issues", "best practices", "anomalies") return the relevant raw fields and let the LLM reason. Do not hardcode evaluation heuristics in Python. IMPORTS: The following modules are pre-imported - do not write any import statements: asyncio, collections, csv, dataclasses, datetime, decimal, enum, fractions, functools, itertools, json, math, re, statistics, string, time, typing, uuid, ClientError from botocore, io (StringIO, BytesIO only). Do not re-import. EXAMPLES: Parallel calls: `python buckets, funcs = await asyncio.gather( call_boto3(service_name='s3',operation_name='ListBuckets'), call_boto3(service_name='lambda',operation_name='ListFunctions'), return_exceptions=True, ) result = { 'buckets':len(buckets.get('Buckets',\[\])) if isinstance(buckets,dict) else f'ERR:{buckets}', 'functions':len(funcs.get('Functions',\[\])) if isinstance(funcs,dict) else f'ERR:{funcs}'} result ` Multi-region: `python regions = \[r\['RegionName'\] for r in (await call_boto3(service_name='ec2', operation_name='DescribeRegions'))\['Regions'\]\] responses = await asyncio.gather(*\[call_boto3(service_name='ec2', operation_name='DescribeInstances', region_name=r) for r in regions\], return_exceptions=True) result = {r: len(\[i for rv in res.get('Reservations',\[\]) for i in rv\['Instances'\]\]) for r,res in zip(regions,responses) if isinstance(res,dict)} result ` List→Describe (auto-paginated - no token loop needed): `python r = await call_boto3(service_name='dynamodb', operation_name='ListTables') tables = r\['TableNames'\] result = await asyncio.gather(*\[call_boto3(service_name='dynamodb', operation_name='DescribeKinesisStreamingDestination', params={'TableName': t}) for t in tables\], return_exceptions=True) result ` * **get regional availability** — AWS resource availability per region. - Max 10 regions; multi-region needs `filters`; single-region supports `next_token`. - Status: isAvailableIn | isNotAvailableIn | isPlannedIn | Not Found. - Response key: products | service\_apis | cfn\_resources. Not for region counts/docs/vague queries -- use `search_documentation` / `list_regions`. Filter values must EXACTLY match AWS's catalog names; guessed, partial, or pluralized names are rejected ("values in filter parameter do not exist"). If unsure of the exact name, first call once for a single region with resource\_type set and NO filters to list all valid names, then re-call filtering on the exact match. * **list regions** — Retrieve a list of all AWS regions. * **read documentation** — Fetch full AWS doc pages as markdown. `search_documentation` already returns verbatim page chunks, so don't re-read a URL whose chunk you already have to "confirm" or "round out" an answer -- the chunk is the real page text; treat it as authoritative. Reading the full page is justified ONLY when the chunks genuinely lack the content: - an enumeration or aggregation ("list all X", "how many X") needs the complete set and the chunks show only part of it; - no search result is on-topic after refining the query, and a known doc URL would have the answer. Otherwise, answer from the chunks. Use exact URLs from `search_documentation`; don't guess slugs. Input: `requests: \[{url, max_length?, start_index?}\]`. Batch 2-5. - `max_length` default 10000. - `start_index` default 0; use prior `end_index` to continue, TOC offset to jump. Allow-listed prefixes: docs.aws.amazon.com; aws.amazon.com (not /marketplace); repost.aws/knowledge-center; docs.amplify.aws; ui.docs.amplify.aws; github.com/\{aws-cloudformation/aws-cloudformation-templates, aws-samples/\{aws-cdk-examples, generative-ai-cdk-constructs-samples, serverless-patterns}, awsdocs/aws-cdk-guide, awslabs/aws-solutions-constructs, cdklabs/cdk-nag} (README on `main`); constructs.dev/packages/\{@aws-cdk-containers, @aws-cdk, @cdk-cloudformation, aws-analytics-reference-architecture, aws-cdk-lib, cdk-amazon-chime-resources, cdk-aws-lambda-powertools-layer, cdk-ecr-deployment, cdk-lambda-powertools-python-layer, cdk-serverless-clamscan, cdk8s, cdk8s-plus-33}; strandsagents.com/latest/documentation/docs/. Output: SUCCESS -- markdown + `total_length, start_index, end_index, truncated, redirected_url?` (truncated includes TOC with char ranges). ERROR -- `error_code` in \{not\_found, invalid\_url, throttled, downstream\_error, validation\_error}. * **retrieve skill** — Retrieve an AWS skill (workflows, references). Returns SKILL.md, or `file` if given. Call `search_documentation` FIRST and copy `skill_name` verbatim -- it is an opaque registry ID. Never guess or fabricate `skill_name` or `file`. * **search documentation** — AWS docs search. Each result's `context` is verbatim page text -- a real chunk of the actual page, not a short snippet -- and usually already contains the answer, so answer directly from it. Use `read_documentation` only when the chunks genuinely lack the needed detail. Pick ONE topic. Add a 2nd ONLY if query genuinely spans domains. Extra topics dilute ranking. - reference\_documentation -- API/SDK/CLI specs, config params - current\_awareness -- new/released/announced - troubleshooting -- errors, "how to fix" (NOT for conceptual/feature questions) - amplify\_docs -- Amplify (+ language) - cdk\_docs -- CDK concepts/guides - cdk\_constructs -- CDK code samples, L3 - cloudformation -- CFN/SAM templates - strands\_docs -- Strands Agents SDK (its Skills/agents concepts go here, NOT agent\_skills) - agent\_skills -- this tool's guided skills (load via `retrieve_skill`) - general (default) -- architecture, best practices, tutorials, feature behavior Results: rank\_order (lower=better), url, title, context (verbatim page chunk -- answer directly from it). ## Connect AWS to an AI agent Add AWS from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # Message agent tools for AI agents Source: https://trytilde.ai/docs/tool-providers/chatkit-agent-message Explore 2 Message agent tools for AI agents in Tilde, including supported authentication and MCP capabilities. Send a ChatKit message to the agent bound to this provider and stream its response. Tilde exposes **2 Message agent tools** for AI agents through MCP. Connect with No Auth. ## Popular Message agent tools * **message** — Send a message to this agent. Returns immediately with a ticket; call wait\_for\_response with that ticket. * **wait\_for\_response** — Subscribe to the child agent's real-time ChatKit response. Streaming deltas are delivered as MCP progress notifications (or logging notifications when no progress token is supplied) and the final result is the canonical ChatKit message. ## Connect Message agent to an AI agent Add Message agent from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # Message internal agent tools for AI agents Source: https://trytilde.ai/docs/tool-providers/chatkit-internal-agent Explore 0 Message internal agent tools for AI agents in Tilde, including supported authentication and MCP capabilities. Send messages between paired ChatKit agents through an internal ChatKit session. Tilde exposes **0 Message internal agent tools** for AI agents through MCP. No authentication method is currently advertised. ## Message internal agent tools This provider does not currently publish tools in the public catalog. ## Connect Message internal agent to an AI agent Add Message internal agent from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # E2B Sandbox tools for AI agents Source: https://trytilde.ai/docs/tool-providers/e2b-sandbox Explore 34 E2B Sandbox tools for AI agents in Tilde, including supported authentication and MCP capabilities. E2B sandbox management, filesystem, patch, and command execution tools. Tilde exposes **34 E2B Sandbox tools** for AI agents through MCP. Connect with E2B API key. ## Popular E2B Sandbox tools * **Check E2B API health** — Check the E2B API health endpoint. * **Create E2B sandbox** — Create a new E2B sandbox from a template. * **Connect E2B sandbox** — Connect to an existing E2B sandbox and extend its TTL. * **Get E2B sandbox** — Get details for a specific E2B sandbox. * **List E2B sandboxes** — List running and paused E2B sandboxes. * **Delete E2B sandbox** — Terminate an E2B sandbox. * **Pause E2B sandbox** — Pause an E2B sandbox. * **Refresh E2B sandbox** — Refresh an E2B sandbox TTL. * **Set E2B sandbox timeout** — Set an E2B sandbox timeout. * **Get E2B sandbox logs** — Get logs for a specific E2B sandbox. * **Get E2B sandbox metrics** — Get metrics for a specific E2B sandbox. * **Get E2B sandbox events** — Get lifecycle events for a specific E2B sandbox. ## Connect E2B Sandbox to an AI agent Add E2B Sandbox from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # Firecrawl tools for AI agents Source: https://trytilde.ai/docs/tool-providers/firecrawl Explore 26 Firecrawl tools for AI agents in Tilde, including supported authentication and MCP capabilities. Firecrawl web search, scraping, crawling, extraction, monitor, interact, parse, feedback, agent, and research tools. Tilde exposes **26 Firecrawl tools** for AI agents through MCP. Connect with Firecrawl API key. ## Popular Firecrawl tools * **Scrape a URL** — Scrape one URL with Firecrawl and return clean markdown, JSON extraction, screenshots, links, branding data, or other requested formats. * **Map a website** — Discover URLs on a site before deciding what to scrape or crawl. * **Search the web** — Search the web with Firecrawl and optionally scrape returned results. * **Send search feedback** — Submit feedback for a previous Firecrawl search result. * **Send endpoint feedback** — Submit endpoint-level feedback for scrape, parse, map, or search jobs. * **Run a site crawl** — Start a Firecrawl crawl job and poll until a terminal status is reached. * **Get crawl status** — Fetch the current status and available results for an existing crawl job. * **Extract structured data** — Extract structured information from one or more URLs with Firecrawl extraction. * **Start a research agent** — Start an asynchronous Firecrawl autonomous web research agent job. * **Get agent status** — Poll an existing Firecrawl agent job for status and results. * **Interact with a page** — Open or reuse a Firecrawl scrape browser session and execute a prompt or code interaction. * **Stop interact session** — Stop a Firecrawl interact session for a scrape id. ## Connect Firecrawl to an AI agent Add Firecrawl from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # GitHub tools for AI agents Source: https://trytilde.ai/docs/tool-providers/github Explore 78 GitHub tools for AI agents in Tilde, including supported authentication and MCP capabilities. GitHub developer workflow tools for issues, pull requests, code, Actions, checks, releases, reactions, search, users, and organizations. Tilde exposes **78 GitHub tools** for AI agents through MCP. Connect with Personal access token, OAuth app, GitHub App, Tilde-managed OAuth. ## Popular GitHub tools * **Create Issue** — Create a GitHub issue. * **Update Issue** — Update GitHub issue fields. * **Get Issue** — Get a GitHub issue. * **Search Issues** — Search GitHub issues and pull requests. * **List Issue Comments** — List issue or PR conversation comments. * **Add Issue Comment** — Add an issue or PR conversation comment. * **Update Issue Comment** — Update an issue comment. * **Delete Issue Comment** — Delete an issue comment. * **List Labels** — List repository labels. * **Add Labels To Issue** — Add labels to an issue. * **Remove Label From Issue** — Remove a label from an issue. * **List Milestones** — List repository milestones. ## Connect GitHub to an AI agent Add GitHub from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # Google Analytics tools for AI agents Source: https://trytilde.ai/docs/tool-providers/google-analytics Explore 74 Google Analytics tools for AI agents in Tilde, including supported authentication and MCP capabilities. Google Analytics tools for GA4 Admin, Data API reports, audience exports/lists, report tasks, and Measurement Protocol events. Tilde exposes **74 Google Analytics tools** for AI agents through MCP. Connect with Tilde-managed Google OAuth. ## Popular Google Analytics tools * **Archive Conversion Event** — Archive a deprecated GA4 conversion event. * **Archive Custom Dimension** — Archive a GA4 custom dimension. * **Batch Run Pivot Reports** — Run multiple GA4 pivot reports in one request. * **Batch Run Reports** — Run multiple GA4 reports in one request. * **Check Compatibility** — Check GA4 dimension and metric compatibility. * **Create Audience Export** — Create a GA4 audience export. * **Create Audience List** — Create a GA4 audience list. * **Create Conversion Event** — Create a deprecated GA4 conversion event. * **Create Custom Dimension** — Create a GA4 custom dimension. * **Create Custom Metric** — Create a GA4 custom metric. * **Create Data Stream** — Create a data stream for a GA4 property. * **Create Expanded Data Set** — Create an expanded data set for a GA4 property. ## Connect Google Analytics to an AI agent Add Google Analytics from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # Google Calendar tools for AI agents Source: https://trytilde.ai/docs/tool-providers/google-calendar Explore 9 Google Calendar tools for AI agents in Tilde, including supported authentication and MCP capabilities. Google Calendar integration for managing events, scheduling, and calendar access. Tilde exposes **9 Google Calendar tools** for AI agents through MCP. Connect with Tilde-managed OAuth. ## Popular Google Calendar tools * **Create a calendar event** — Create a calendar event with attendees, location, description, and optional Google Meet link * **Search calendar events** — Search events by text query within a time range * **List upcoming events** — List upcoming events on a calendar. Defaults to next 7 days. * **Find free time slots** — Find available time slots across calendars within a date range * **Update a calendar event** — Update an existing calendar event * **Delete a calendar event** — Delete a calendar event * **RSVP to a calendar event** — Respond to a calendar event invitation * **List calendars** — List all calendars the user has access to * **Get current date and time** — Get current date and time. Essential for relative scheduling since agents have no clock. ## Connect Google Calendar to an AI agent Add Google Calendar from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # Google Docs tools for AI agents Source: https://trytilde.ai/docs/tool-providers/google-docs Explore 6 Google Docs tools for AI agents in Tilde, including supported authentication and MCP capabilities. Google Docs integration for creating, reading, and editing documents. Tilde exposes **6 Google Docs tools** for AI agents through MCP. Connect with Tilde-managed OAuth. ## Popular Google Docs tools * **Create a new Google Doc with optional initial content** — Create a new Google Doc with optional initial content * **Retrieve a document's content as plain text** — Retrieve a document's content as plain text * **Append text to the end of a document** — Append text to the end of a document * **Insert text at a specific position in a document** — Insert text at a specific position in a document * **Find and replace text within a document** — Find and replace text within a document * **Create a copy of an existing document** — Create a copy of an existing document ## Connect Google Docs to an AI agent Add Google Docs from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # Google Drive tools for AI agents Source: https://trytilde.ai/docs/tool-providers/google-drive Explore 10 Google Drive tools for AI agents in Tilde, including supported authentication and MCP capabilities. Google Drive integration for searching, uploading, downloading, and managing files and folders. Tilde exposes **10 Google Drive tools** for AI agents through MCP. Connect with Tilde-managed OAuth. ## Popular Google Drive tools * **Search for files and folders using Drive query syntax** — Search for files and folders in Google Drive using query syntax. Example: "name contains 'report'". * **Get metadata for a file** — Get detailed metadata for a file in Google Drive. * **Download a file. For Google Workspace files, exports to specified format.** — Download a file from Google Drive. For Google Workspace files (Docs, Sheets, Slides), exports to the specified format. * **Upload a file to Drive** — Upload a file to Google Drive. Content must be base64-encoded. Uses multipart upload. * **Create a new folder** — Create a new folder in Google Drive. * **Share a file with users or make it public** — Share a file or folder in Google Drive with specific users or make it publicly accessible. * **Move a file to a different folder** — Move a file to a different folder in Google Drive. * **Create a copy of a file** — Create a copy of a file in Google Drive. * **Move a file to trash** — Move a file to the trash in Google Drive (does not permanently delete). * **Create a new file from text content** — Create a new file in Google Drive from plain text content. ## Connect Google Drive to an AI agent Add Google Drive from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # Google Mail tools for AI agents Source: https://trytilde.ai/docs/tool-providers/google-mail Explore 11 Google Mail tools for AI agents in Tilde, including supported authentication and MCP capabilities. Google Mail integration for sending and reading emails via the Gmail API. Tilde exposes **11 Google Mail tools** for AI agents through MCP. Connect with Tilde-managed OAuth. ## Popular Google Mail tools * **Send an email** — Send an email via Gmail API. Requires appropriate Gmail scopes. * **Search and retrieve emails** — Search and retrieve emails using Gmail search syntax * **Retrieve a single email by ID** — Retrieve a single email by ID with full headers, body, and attachment metadata * **Retrieve all messages in a conversation thread** — Retrieve all messages in a conversation thread * **Send a reply within an existing email thread** — Send a reply within an existing email thread * **Create an email draft without sending** — Create an email draft without sending * **Move a message to trash** — Move a message to trash * **Add or remove labels from a message** — Add or remove labels from a message * **List all labels** — List all labels * **Create a new user label** — Create a new user label * **Download an attachment from an email** — Download an attachment from an email ## Connect Google Mail to an AI agent Add Google Mail from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # Google Search Console tools for AI agents Source: https://trytilde.ai/docs/tool-providers/google-search-console Explore 19 Google Search Console tools for AI agents in Tilde, including supported authentication and MCP capabilities. Google Search Console tools for property management, search analytics, URL inspection, indexing diagnostics, and sitemap management. Tilde exposes **19 Google Search Console tools** for AI agents through MCP. Connect with Tilde-managed OAuth. ## Popular Google Search Console tools * **Get Google Search Console tool capabilities and auth status** — Lists available Google Search Console tools, grouped by category, and reports whether the current credential can call Search Console. * **List Google Search Console properties** — Lists all Google Search Console sites/properties visible to the connected Google account. * **Get Search Console property details** — Gets verification, ownership, and permission details for a specific Search Console property. * **Add a Search Console property** — Adds a site to the connected Google Search Console account. * **Delete a Search Console property** — Removes a site from the connected Google Search Console account. * **Get Search Console analytics** — Returns top Search Console rows for a property over a recent time window. * **Get Search Console performance overview** — Returns total Search Console performance metrics and daily trend data for a property. * **Compare Search Console periods** — Compares clicks, impressions, CTR, and position between two date ranges. * **Get queries for a page** — Returns Search Console query performance for a specific page URL. * **Get advanced Search Console analytics** — Returns Search Console analytics with date range, search type, filters, sorting, and pagination. * **Inspect a URL in Search Console** — Returns URL inspection, crawl, indexing, canonical, and rich result details for one URL. * **Inspect URLs in batch** — Inspects up to 10 URLs and returns compact URL inspection summaries. ## Connect Google Search Console to an AI agent Add Google Search Console from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # Google Sheets tools for AI agents Source: https://trytilde.ai/docs/tool-providers/google-sheets Explore 10 Google Sheets tools for AI agents in Tilde, including supported authentication and MCP capabilities. Google Sheets integration for reading, writing, and managing spreadsheet data. Tilde exposes **10 Google Sheets tools** for AI agents through MCP. Connect with Tilde-managed OAuth. ## Popular Google Sheets tools * **Read data from a cell range in A1 notation** — Read data from a cell range in A1 notation (e.g. "Sheet1!A1:D10"). * **Write data to a cell range** — Write data to a cell range. Values are interpreted as if typed by the user (USER\_ENTERED). * **Append rows to the end of a sheet's data** — Append rows to the end of a sheet's existing data. * **Find rows matching criteria in a column** — Search for rows where a given column matches a value using the specified operator (equals, contains, greater\_than, less\_than). The column can be identified by letter or by its header name in the first row. * **Create a new spreadsheet** — Create a new Google Sheets spreadsheet with an optional initial sheet name. * **List all worksheets in a spreadsheet** — List all worksheet tabs and their properties in a spreadsheet. * **Add a new worksheet tab** — Add a new worksheet tab to an existing spreadsheet. * **Get metadata about a spreadsheet** — Retrieve metadata about a spreadsheet including its title, URL, locale, and worksheet list. * **Clear cell contents while preserving formatting** — Clear the contents of cells in a range while preserving formatting. * **Apply formatting to cells** — Apply formatting (bold, italic, text colour, background colour) to a range of cells. ## Connect Google Sheets to an AI agent Add Google Sheets from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # Tool providers for AI agents Source: https://trytilde.ai/docs/tool-providers/index Browse Tilde tool providers for AI agents, compare authentication options, and explore MCP tools for GitHub, Slack, Google, Stripe, and more. Browse Tilde integrations for AI agents, including GitHub, Slack, Google Workspace, Stripe, Notion, and more. Search each provider to compare supported authentication methods and inspect its available MCP tools. The catalog loads provider names, descriptions, tools, authentication methods, and available icon metadata from Tilde's public API. It remains accessible without a Tilde account. Compare Tilde-managed authentication with self-managed credentials. # Linq tools for AI agents Source: https://trytilde.ai/docs/tool-providers/linq Explore 24 Linq tools for AI agents in Tilde, including supported authentication and MCP capabilities. Send and manage Linq iMessage, RCS, and SMS conversations, reactions, polls, phone lines, contact cards, capabilities, block lists, and webhook subscriptions through the Partner API V3. Tilde exposes **24 Linq tools** for AI agents through MCP. Connect with Linq API token. ## Popular Linq tools * **Send a Linq message** — Send to recipients without choosing a from line. This is the recommended Linq path because it reuses healthy chats and load-balances/fails over across the account's line pool. * **Send to an existing Linq chat** — Send a message in an existing Linq chat after checking its current health status. A 2024 opt-out response is terminal and must not be retried. * **List Linq chats** — Call the corresponding Linq Partner API V3 operation using the managed account credential. * **Get a Linq chat** — Call the corresponding Linq Partner API V3 operation using the managed account credential. * **List messages in a Linq chat** — Call the corresponding Linq Partner API V3 operation using the managed account credential. * **Get a Linq message** — Call the corresponding Linq Partner API V3 operation using the managed account credential. * **Edit a Linq message** — Call the corresponding Linq Partner API V3 operation using the managed account credential. * **Delete a Linq message** — Call the corresponding Linq Partner API V3 operation using the managed account credential. * **Add or remove a Linq reaction** — Call the corresponding Linq Partner API V3 operation using the managed account credential. * **Create a Linq poll** — Call the corresponding Linq Partner API V3 operation using the managed account credential. * **Get a Linq poll** — Call the corresponding Linq Partner API V3 operation using the managed account credential. * **Add options to a Linq poll** — Call the corresponding Linq Partner API V3 operation using the managed account credential. ## Connect Linq to an AI agent Add Linq from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # Tilde-managed authentication for tool providers Source: https://trytilde.ai/docs/tool-providers/managed-auth Learn how Tilde-managed OAuth connects AI agents to tool providers securely, and compare managed authentication with self-managed credentials. Tilde-managed authentication lets a user connect an AI agent to a supported tool provider without requiring you to register an OAuth app or store its client credentials. Tilde runs the OAuth flow, encrypts the resulting tokens, and refreshes them when the provider supports it. Look for the **Tilde-managed OAuth** badge in the [Tool Providers catalog](/docs/tool-providers). You can use managed auth for one provider and your own credentials for another. ## Self-managed vs Tilde-managed authentication Use Tilde's OAuth app. You do not configure a client ID, client secret, redirect URL, or token refresh. Use this option when you want the shortest path to connecting users and do not need a custom consent screen or provider-specific scopes. Bring your own OAuth app, API key, access token, service account, or provider app credentials. Use this option when you need your brand on the consent screen, custom scopes, a dedicated provider app, or an authentication method that Tilde does not manage. ## How Tilde-managed OAuth works With Tilde-managed OAuth, you do not need to: * Register an OAuth app with the upstream provider. * Distribute a client ID or client secret. * Build an authorization callback route. * Store access or refresh tokens in your application. * Refresh expired access tokens. When your agent needs a connected account, Tilde starts a credential-brokering flow. The user authorizes access on the provider's site. Tilde stores the resulting credential outside the model context and associates it with the configured tool provider. Open **Tools** → **Configure Tools** in Tilde. Select a provider with the **Tilde-managed OAuth** badge. Click **Add provider** and choose **Tilde-managed OAuth**. You do not enter OAuth app credentials. Continue to the provider's authorization page. Review the requested access and approve the connection. Open the configured provider and enable only the tools your agent needs. Add those tools to an MCP server when you are ready to expose them to an agent. ## When to use self-managed authentication Use your own credentials when you need to: * Show your own app name and branding on the provider's consent screen. * Request scopes that differ from the Tilde-managed app. * Control the upstream app's installation or approval policy. * Connect with an API key, personal access token, service account, or another non-OAuth credential. * Use a provider that does not show the **Tilde-managed OAuth** badge. For OAuth apps, create the app with the upstream provider first. Tilde shows the callback URL to register. You then enter the client ID and client secret, name the connection, and authorize the user account. For API keys and tokens, enter the credential requested by the provider setup form. Self-managed authentication does not pass provider secrets to the model. Tilde encrypts stored credentials and injects them only when it invokes the selected tool. ## Compare managed and self-managed authentication | | Tilde-managed auth | Self-managed auth | | ----------------------------- | -------------------------- | ----------------------------------------------- | | OAuth app owner | Tilde | Your organization | | Client credentials | Managed by Tilde | Supplied by you | | Consent screen branding | Tilde's provider app | Your provider app | | Scopes | Tilde's supported defaults | Scopes configured in your app | | Token storage and refresh | Managed by Tilde | Managed by Tilde | | API keys and service accounts | Not applicable | Supplied by you | | Setup effort | Connect the user account | Configure credentials, then connect the account | ## Mix managed and self-managed connections Authentication is selected per configured provider account. Your workspace can use Tilde-managed OAuth for Google Mail, a self-managed GitHub App for repository automation, and an API key for Stripe at the same time. Choose the narrowest upstream permissions that support the tools you enable. Keep separate provider accounts when agents need different access boundaries. Check supported authentication methods and inspect the tools available from each provider. # Modal Sandbox tools for AI agents Source: https://trytilde.ai/docs/tool-providers/modal-sandbox Explore 10 Modal Sandbox tools for AI agents in Tilde, including supported authentication and MCP capabilities. Modal sandbox management, filesystem, patch, and command execution tools. Tilde exposes **10 Modal Sandbox tools** for AI agents through MCP. Connect with Modal token. ## Popular Modal Sandbox tools * **Create Modal sandbox** — Run a Modal sandbox management, filesystem, or shell operation. * **Get Modal sandbox** — Run a Modal sandbox management, filesystem, or shell operation. * **Terminate Modal sandbox** — Run a Modal sandbox management, filesystem, or shell operation. * **Read file in Modal** — Run a Modal sandbox management, filesystem, or shell operation. * **Write file in Modal** — Run a Modal sandbox management, filesystem, or shell operation. * **Delete file in Modal** — Run a Modal sandbox management, filesystem, or shell operation. * **List directory in Modal** — Run a Modal sandbox management, filesystem, or shell operation. * **Stat path in Modal** — Run a Modal sandbox management, filesystem, or shell operation. * **Execute command in Modal** — Run a Modal sandbox management, filesystem, or shell operation. * **Apply patch in Modal** — Run a Modal sandbox management, filesystem, or shell operation. ## Connect Modal Sandbox to an AI agent Add Modal Sandbox from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # Payload CMS tools for AI agents Source: https://trytilde.ai/docs/tool-providers/payload Explore 7 Payload CMS tools for AI agents in Tilde, including supported authentication and MCP capabilities. Payload CMS document and global content management tools backed by Payload's REST API. Tilde exposes **7 Payload CMS tools** for AI agents through MCP. Connect with Payload API key. ## Popular Payload CMS tools * **Find Payload documents** — Find documents in a Payload collection by collection slug, optional ID, pagination, sorting, and filters. * **Count Payload documents** — Count documents in a Payload collection by collection slug and optional filters. * **Create Payload document** — Create a document in a Payload collection using the generated REST API. * **Update Payload document** — Update one Payload document by ID, or multiple documents with a where filter. * **Delete Payload documents** — Delete one Payload document by ID, or multiple documents with a where filter. * **Find Payload global** — Fetch a Payload global singleton by global slug. * **Update Payload global** — Update a Payload global singleton by global slug. ## Connect Payload CMS to an AI agent Add Payload CMS from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # PostHog tools for AI agents Source: https://trytilde.ai/docs/tool-providers/posthog Explore 66 PostHog tools for AI agents in Tilde, including supported authentication and MCP capabilities. PostHog product analytics, feature flags, insights, dashboards, cohorts, surveys, experiments, persons, events, annotations, alerts, and project tools backed by direct PostHog REST APIs. Tilde exposes **66 PostHog tools** for AI agents through MCP. Connect with PostHog API key. ## Popular PostHog tools * **List projects** — List PostHog projects. Native direct PostHog API tool derived from Nango's PostHog integration templates. Provide path fields such as `project_id` and `id`, list filters in `query`, and create/update fields in `data`. * **Get project** — Retrieve one PostHog project. Native direct PostHog API tool derived from Nango's PostHog integration templates. Provide path fields such as `project_id` and `id`, list filters in `query`, and create/update fields in `data`. * **Capture event** — Capture an event through PostHog's capture API. Requires a project API token in the tool parameters. Native direct PostHog API tool derived from Nango's PostHog integration templates. Provide path fields such as `project_id` and `id`, list filters in `query`, and create/update fields in `data`. * **Identify person** — Identify or update a person by fetching the project API token, then sending a `$identify` capture event. Native direct PostHog API tool derived from Nango's PostHog integration templates. Provide path fields such as `project_id` and `id`, list filters in `query`, and create/update fields in `data`. * **Create person** — Create a PostHog person by sending an identify event, then reading the person by distinct\_id. Native direct PostHog API tool derived from Nango's PostHog integration templates. Provide path fields such as `project_id` and `id`, list filters in `query`, and create/update fields in `data`. * **List persons** — List PostHog persons for a project. Native direct PostHog API tool derived from Nango's PostHog integration templates. Provide path fields such as `project_id` and `id`, list filters in `query`, and create/update fields in `data`. * **Get person** — Retrieve a PostHog person. Native direct PostHog API tool derived from Nango's PostHog integration templates. Provide path fields such as `project_id` and `id`, list filters in `query`, and create/update fields in `data`. * **Update person** — Update a PostHog person. Native direct PostHog API tool derived from Nango's PostHog integration templates. Provide path fields such as `project_id` and `id`, list filters in `query`, and create/update fields in `data`. * **Delete person** — Delete or archive a PostHog person. Native direct PostHog API tool derived from Nango's PostHog integration templates. Provide path fields such as `project_id` and `id`, list filters in `query`, and create/update fields in `data`. * **List feature flags** — List PostHog feature flags. Native direct PostHog API tool derived from Nango's PostHog integration templates. Provide path fields such as `project_id` and `id`, list filters in `query`, and create/update fields in `data`. * **Get feature flag** — Retrieve a PostHog feature flag. Native direct PostHog API tool derived from Nango's PostHog integration templates. Provide path fields such as `project_id` and `id`, list filters in `query`, and create/update fields in `data`. * **Create feature flag** — Create a PostHog feature flag. Native direct PostHog API tool derived from Nango's PostHog integration templates. Provide path fields such as `project_id` and `id`, list filters in `query`, and create/update fields in `data`. ## Connect PostHog to an AI agent Add PostHog from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # Sentry tools for AI agents Source: https://trytilde.ai/docs/tool-providers/sentry Explore 237 Sentry tools for AI agents in Tilde, including supported authentication and MCP capabilities. Sentry issue discovery, event investigation, assignment, status, and activity-note tools. The deduplicated catalog includes 48 official Sentry MCP definitions and 211 Composio aliases; Nango contributes 0 actions. Inputs and outputs use the upstream JSON schemas. Tilde exposes **237 Sentry tools** for AI agents through MCP. Connect with Sentry auth token, Sentry OAuth app, Tilde-managed OAuth. ## Popular Sentry tools * **Who am I** — Return the authenticated Sentry user. * **Find organizations** — Find Sentry organizations accessible to the authenticated user. * **Find projects** — Find projects in a Sentry organization. * **Search issues** — Search Sentry issues using Sentry issue-search syntax. Defaults to unresolved issues. * **Get issue details** — Get strongly typed details for one Sentry issue. * **Get issue activity** — Get activity and human comments for one Sentry issue. * **Search issue events** — Search the error events grouped into one Sentry issue. * **Get event stacktrace** — Retrieve a full issue event, including stacktrace entries when Sentry provides them. * **Update issue** — Assign an issue or update its status. This mutates visible Sentry state. * **Add issue note** — Add a human-visible comment to a Sentry issue activity feed. * **add team to project** — Grant a team access to an existing Sentry project. Use this tool when you need to: - Add another team to a project - Grant a team access without changing project metadata - Check whether a team already has project access before adding it \ add\_team\_to\_project(organizationSlug='my-organization', projectSlug='my-project', teamSlug='my-team') \ \ - Team access changes are separate from project metadata updates. - If the team is already assigned, this tool returns the current team list without making another change. \ * **analyze issue with seer** — Use Seer to analyze production errors and get detailed root cause analysis with specific code fixes. Use this tool when: - The user explicitly asks for root cause analysis, Seer analysis, or help fixing/debugging an issue - You are unable to accurately determine the root cause from the issue details alone Do NOT call this tool as an automatic follow-up to get\_sentry\_resource. What this tool provides: - Root cause analysis with code-level explanations - Specific file locations and line numbers where errors occur - Concrete code fixes you can apply - Step-by-step implementation guidance This tool automatically: 1. Checks if analysis already exists (instant results) 2. Starts new AI analysis if needed (\~2-5 minutes) 3. Returns complete fix recommendations \ ### User: "Run Seer on this issue" `analyze_issue_with_seer(issueUrl='https://my-org.sentry.io/issues/PROJECT-1Z43')` ### User: "Analyze this issue and suggest a fix" `analyze_issue_with_seer(organizationSlug='my-organization', issueId='ERROR-456')` \ \ - Only use when the user explicitly requests analysis or you cannot determine the root cause from issue details alone - Seer Autofix does not support metric alert issues (issueCategory: metric); use get\_issue\_details and search\_events instead - If the user provides an issueUrl, extract it and use that parameter alone - The analysis includes actual code snippets and fixes, not just error descriptions - Results are cached - subsequent calls return instantly \ ## Connect Sentry to an AI agent Add Sentry from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # Slack tools for AI agents Source: https://trytilde.ai/docs/tool-providers/slack Explore 53 Slack tools for AI agents in Tilde, including supported authentication and MCP capabilities. Slack messaging tools backed by a configured Slack bot. Tilde exposes **53 Slack tools** for AI agents through MCP. Connect with Tilde-managed OAuth, Slack app. ## Popular Slack tools * **Send a Slack message** — Send a message to a Slack channel. * **Reply in a Slack thread** — Reply to an existing Slack thread. * **List Slack channels** — List Slack conversations visible to the bot. * **Add a Slack reaction** — Add a reaction to a Slack message. * **Archive a Slack channel** — Archive a Slack channel. * **Get Slack channel info** — Retrieve conversation details including topic, purpose, and membership state. * **Invite users to a Slack channel** — Invite users to a Slack channel. * **Set Slack channel purpose** — Update a channel's purpose text for a conversation. * **Set Slack channel topic** — Set the topic of a channel. * **Unarchive a Slack channel** — Restore an archived conversation so members can use it again. * **Set Slack channel workspaces** — Set the workspaces in an Enterprise Grid org that connect to a channel. * **Create a Slack channel** — Create a new public or private Slack channel by name. ## Connect Slack to an AI agent Add Slack from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # Stripe tools for AI agents Source: https://trytilde.ai/docs/tool-providers/stripe Explore 1 Stripe tools for AI agents in Tilde, including supported authentication and MCP capabilities. Stripe payment processing integration. Tilde exposes **1 Stripe tool** for AI agents through MCP. Connect with API Key. ## Popular Stripe tools * **Process a refund** — Process a refund via the Stripe API. ## Connect Stripe to an AI agent Add Stripe from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # Tavily tools for AI agents Source: https://trytilde.ai/docs/tool-providers/tavily Explore 6 Tavily tools for AI agents in Tilde, including supported authentication and MCP capabilities. Tavily web search, extraction, crawl, map, research, and account usage tools. Tilde exposes **6 Tavily tools** for AI agents through MCP. Connect with Tavily API key. ## Popular Tavily tools * **Search the web** — Run a Tavily web search and return ranked results, optional answers, images, raw content, and usage. * **Extract web content** — Extract cleaned content from one or more URLs with Tavily Extract. * **Crawl a website** — Crawl a website from a root URL with configurable depth, breadth, path/domain selection, and extraction options. * **Map a website** — Map a website structure from a root URL and return discovered URLs. * **Research a topic** — Create a Tavily research task and poll until completion, returning the synthesized content. * **Get usage** — Return usage information for the Tavily API key. ## Connect Tavily to an AI agent Add Tavily from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # Tilde Browser tools for AI agents Source: https://trytilde.ai/docs/tool-providers/tilde-browser Explore 0 Tilde Browser tools for AI agents in Tilde, including supported authentication and MCP capabilities. Browserbase-backed Web Browser tools with Tilde managed credential fill. Tilde exposes **0 Tilde Browser tools** for AI agents through MCP. No authentication method is currently advertised. ## Tilde Browser tools This provider does not currently publish tools in the public catalog. ## Connect Tilde Browser to an AI agent Add Tilde Browser from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # Tilde Control Plane tools for AI agents Source: https://trytilde.ai/docs/tool-providers/tilde-control-plane Explore 66 Tilde Control Plane tools for AI agents in Tilde, including supported authentication and MCP capabilities. Authenticated team-scoped Tilde control-plane tools. Team context is inferred from the MCP server/tool instance; org and team administration tools are intentionally hidden. Tilde exposes **66 Tilde Control Plane tools** for AI agents through MCP. Connect with No Auth. ## Popular Tilde Control Plane tools * **tilde\_whoami** — Return the authenticated Tilde identity, organizations, teams, and groups. * **tilde\_enable\_toolkit\_provider** — Create or configure a toolkit provider instance for a team. Choose a credential\_source\_type\_id from capability search results. When credentials are required, send approval\_url to the user and immediately invoke the returned next\_tool\_name with next\_tool\_arguments; do not invoke provider tools until the wait completes. * **tilde\_auto\_provision\_toolkit\_provider** — Provision an upstream provider app and its toolkit provider instance. When browser setup is required, send approval\_url to the user and immediately invoke the returned next\_tool\_name with next\_tool\_arguments. The wait resolves only after provider app setup and any required user credential brokering activate the provider. * **tilde\_set\_toolkit\_tool\_enabled** — Enable or disable one tool inside a configured toolkit provider instance. This does not expose the tool on an MCP server; use tilde\_set\_mcp\_server\_tool\_enabled for that mapping. * **tilde\_enable\_and\_bind\_provider\_tools** — Enable every provider tool or an explicit selection, then bind the enabled tools to one or more Tilde MCP servers in one idempotent operation. Use all\_tools instead of listing ids when every provider tool is required. * **tilde\_connect\_proxied\_mcp\_server** — Connect an upstream MCP server as a Tilde toolkit provider. When credentials are required, send approval\_url to the user and immediately invoke the returned next\_tool\_name with next\_tool\_arguments; discovery remains blocked until the wait completes. * **tilde\_refresh\_proxied\_mcp\_server** — Refresh discovery for an existing proxied MCP server after upstream tool changes and redeploy its discovered tools. * **tilde\_register\_custom\_tool\_backend** — Register a custom HTTP tool backend from a signed discovery manifest and deploy its tools immediately. * **tilde\_refresh\_custom\_tool\_backend** — Refresh discovery for an existing custom HTTP tool backend after manifest changes and redeploy its tools. * **tilde\_generate\_api\_key** — Generate a Tilde API key for a team. * **tilde\_register\_chatkit\_agent** — Register a Vercel AI SDK compatible HTTP ChatKit agent. * **tilde\_configure\_chatkit\_provider** — Create a ChatKit provider/channel, or update the reconciled channel when an explicit id is supplied. ## Connect Tilde Control Plane to an AI agent Add Tilde Control Plane from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # Tilde Human Approval tools for AI agents Source: https://trytilde.ai/docs/tool-providers/tilde-human-approval Explore 1 Tilde Human Approval tools for AI agents in Tilde, including supported authentication and MCP capabilities. No-auth Tilde human approval tools that can be added to any MCP server so agents can wait for secure user approvals. Tilde exposes **1 Tilde Human Approval tool** for AI agents through MCP. Connect with No Auth. ## Popular Tilde Human Approval tools * **wait\_for\_human\_assistance\_to\_complete** — Wait for a previously created human assistance request to be approved, denied, or expired. If the approval has already resolved, this returns immediately. ## Connect Tilde Human Approval to an AI agent Add Tilde Human Approval from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # Tilde Memory Bank tools for AI agents Source: https://trytilde.ai/docs/tool-providers/tilde-memory-bank Explore 4 Tilde Memory Bank tools for AI agents in Tilde, including supported authentication and MCP capabilities. Retain, recall, reflect on, and delete documents in one bound Tilde memory bank. Tilde exposes **4 Tilde Memory Bank tools** for AI agents through MCP. Connect with No Auth. ## Popular Tilde Memory Bank tools * **retain** — Retain or replace one stable document. * **recall** — Recall relevant memories. * **reflect** — Answer using the memory bank. * **delete\_document** — Delete one stable document. ## Connect Tilde Memory Bank to an AI agent Add Tilde Memory Bank from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # Tilde Skill Registry tools for AI agents Source: https://trytilde.ai/docs/tool-providers/tilde-skill-registry Explore 4 Tilde Skill Registry tools for AI agents in Tilde, including supported authentication and MCP capabilities. Registry-specific Tilde skill discovery tools. The registry id is bound server-side on each enabled tool instance. Tilde exposes **4 Tilde Skill Registry tools** for AI agents through MCP. Connect with No Auth. ## Popular Tilde Skill Registry tools * **list\_skills** — List skill names, descriptions, and versions in this bound registry. * **search\_skills** — Search this bound skill registry and return concise summaries before reading full skill content. * **read\_skill\_description** — Read one skill description from this bound registry. * **read\_skill** — Read full content for one skill from this bound registry after progressive discovery. ## Connect Tilde Skill Registry to an AI agent Add Tilde Skill Registry from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # Tilde Pay tools for AI agents Source: https://trytilde.ai/docs/tool-providers/tilde-wallet Explore 0 Tilde Pay tools for AI agents in Tilde, including supported authentication and MCP capabilities. Tilde Pay tools for balances, deposit information, and agent payments. Tilde exposes **0 Tilde Pay tools** for AI agents through MCP. No authentication method is currently advertised. ## Tilde Pay tools This provider does not currently publish tools in the public catalog. ## Connect Tilde Pay to an AI agent Add Tilde Pay from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # Tilde Wiki tools for AI agents Source: https://trytilde.ai/docs/tool-providers/tilde-wiki Explore 44 Tilde Wiki tools for AI agents in Tilde, including supported authentication and MCP capabilities. Maintain Markdown pages, semantic relationships, graph queries, revisions, and media assets in one bound Tilde Wiki. Tilde exposes **44 Tilde Wiki tools** for AI agents through MCP. Connect with No Auth. ## Popular Tilde Wiki tools * **list\_pages** — List or full-text search pages in this wiki. * **grep\_pages** — Run bounded ripgrep-style literal or regular-expression search across Markdown lines in this wiki. * **read\_page** — Read a Markdown page by stable id. * **upsert\_page** — Create or update a page. Updates require expected\_revision. * **move\_page** — Move a page without changing its stable id. * **delete\_page** — Delete a page at an expected revision. * **page\_history** — List immutable page revisions. * **migrate\_page** — Migrate a page to an explicit page type schema version. * **list\_ontology\_templates** — List reusable ontology templates with their page schemas and relationship definitions. * **apply\_ontology\_template** — Install a reusable ontology template into this wiki idempotently. * **list\_page\_types** — List custom page type definitions. * **create\_page\_type** — Create a custom page type with a Draft 7 JSON Schema. ## Connect Tilde Wiki to an AI agent Add Tilde Wiki from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # WhatsApp tools for AI agents Source: https://trytilde.ai/docs/tool-providers/whatsapp Explore 8 WhatsApp tools for AI agents in Tilde, including supported authentication and MCP capabilities. Send WhatsApp text, template, and media messages, mark messages read, fetch media metadata, list approved templates, and inspect the sending number through the Meta Cloud API. Tilde exposes **8 WhatsApp tools** for AI agents through MCP. Connect with WhatsApp Cloud API. ## Popular WhatsApp tools * **Send a WhatsApp text message** — Send free-form text to a WhatsApp user. Only allowed within 24 hours of the user's last message; outside that window Meta returns error 131047 and you must use whatsapp\_send\_template. Bodies over 4096 characters are rejected; split them first. * **Send a WhatsApp template message** — Send an approved message template. This is the only way to start a conversation or reach a user whose 24 hour customer service window has closed. Components carry header, body, and button parameters in Meta's format. * **Send a WhatsApp media message** — Send an image, video, audio, document, or sticker by public link or previously uploaded media id. Subject to the same 24 hour window as text. * **React to a WhatsApp message** — Add an emoji reaction to a message the user sent, or remove one by passing an empty emoji. Reactions are lightweight acknowledgements and do not open or extend the 24 hour window. * **Mark a WhatsApp message read** — Mark an inbound message as read (blue ticks) and optionally show a typing indicator while a reply is being prepared. * **Get WhatsApp media metadata** — Resolve an inbound media id to its download URL, MIME type, and size. The URL is short-lived and must be fetched with the same bearer token. * **List WhatsApp message templates** — List the WhatsApp Business Account's message templates with status, language, category, and components so template sends can be built correctly. * **Get the WhatsApp sending number** — Read the sending number's display number, verified name, quality rating, messaging limit tier, and status. Pause outbound traffic when the status is not CONNECTED. ## Connect WhatsApp to an AI agent Add WhatsApp from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools). [Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth). # Tools Source: https://trytilde.ai/docs/tools Connect your agent to tools through a Tilde MCP server. Tools let your agent act in external systems without exposing provider credentials to the model. ## Personal and workspace ownership Configured tool accounts and MCP servers can belong either to a workspace or to you personally. Personal resources are organization-bound for billing and administration, but they are not attached to a team. Only you and organization or system administrators can manage them. A workspace MCP server can optionally federate personal tools for each connecting user: * **None** exposes only the server's workspace tools. * **All personal tools** adds every active personal tool owned by the caller. * **Selected personal tools** adds only allowed provider and tool definitions that the caller has configured. The selection stores definitions, not credentials or account IDs. When two people connect to the same server, each sees the same workspace tools plus only their own permitted personal accounts. Account-qualified tool names prevent collisions. A personal MCP server exposes personal tools only. An agent can delegate personal tool work within a private conversation while the accounts remain yours. Tilde follows the persisted job and private parent conversations to the original verified human request, then grants the child a short-lived capability for its configured MCP server. The owner, participant access, job generation, and original channel's personal-tool policy are rechecked when the capability is used. Stopping or resuming the job, removing access, or unlinking the original sender invalidates the old delegation. A channel that withholds personal tools cannot gain them through delegation. Owners can promote a personal MCP server to a workspace they belong to. A workspace administrator can make a server personal to themselves only after removing every static workspace-tool mapping; personal tools are always federation-only. To configure this, open an MCP server, choose its personal-tool federation mode, and use **Add tools** in selected mode. The picker shows every available provider definition; the actual runtime catalog is the intersection of that policy and the connecting user's active personal accounts. ## Share without giving up control Tool groups, proxied MCP servers, custom tool providers, MCP server instances, and managed credential roots use independent visibility and ownership planes. For tool and MCP roots, visibility controls safe discovery and use. Ownership controls configuration, tool selection, federation policy, grant management, and deletion. Set either plane to **Team** or **Private**, then add private grants for an Identity user or group. Ownership and administrator access do not make a private resource visible. Credential visibility exposes only redacted metadata needed for discovery. It never authorizes secret retrieval or returns plaintext or decrypted values. Secret configuration, brokering, rotation, and deletion require ownership, while a bound consuming resource receives only the exact capability it needs at execution time. Global MCP and runtime MCP responses do not reveal stored provider secrets. Definitions, configured tools, and runtime mappings inherit their owning tool or MCP root. A shared MCP server resolves caller-specific personal federation after authentication, so one user's accounts and credentials cannot appear in another user's catalog. When Tilde provisions several surfaces for one common provider, the common-provider installation is their policy root. Its live visibility and ownership policy applies to the generated tool group, ChatKit provider, signal provider, and reverse-proxy profiles. Manage the policy at `/api/v1/team/{team_id}/credential/common-provider-installation/{id}`; a bound child cannot widen it independently. Credential secret administration remains separate from provider-bundle visibility. MCP authorization is intersected at execution time: visibility of an MCP server does not by itself authorize a private tool group, and visibility of a tool group does not authorize connection through a private server. [Enable off-the-shelf tool providers](/docs/tool-providers), add custom tools, or proxy upstream APIs. Group them in an MCP server, then connect your agent with the Tilde SDK. Open Tilde, select your workspace, and go to **Tools**. Choose one of these sources: * **Configure Tools** for managed providers such as GitHub, Gmail, and Slack. * **Proxied MCP servers** to connect an existing Streamable HTTP MCP server. * **Custom Tools** to register your own remote tool endpoints. Configure the source's credentials, then enable the tools your agent needs. 1. Go to **Tools** → **MCP Servers** and click **Add MCP server**. 2. Name the server. Enable dynamic mode if the agent should search a large tool catalog instead of loading every tool definition into context. 3. Open the server and add tools from your configured providers, proxied MCP servers, or custom tool providers. 4. Adjust tool names, descriptions, parameters, or fixed inputs as needed. 5. If callers should bring their own personal tools, choose **All personal tools** or **Selected personal tools**. The default is **None**. Keep the MCP server ID. You will pass it to the Tilde SDK in the next step. Install the Tilde SDK and MCP client packages. ```bash theme={"system"} pnpm add @ai-sdk/mcp @trytilde/sdk @trytilde/sdk-vercel-ai-node ``` Add the MCP server ID and your Tilde credentials to the app's environment. Find the organization and team IDs under **Settings** → **Team settings** → **General information**. ```dotenv .env.local theme={"system"} TILDE_API_KEY= TILDE_ORG_ID= TILDE_TEAM_ID= TILDE_MCP_SERVER_ID= ``` Create the Tilde client, then use `process.env.TILDE_MCP_SERVER_ID` when creating the MCP client. ```typescript lib/tilde-tools.ts theme={"system"} import { createClient } from "@trytilde/sdk"; import { createMCPClient } from "@trytilde/sdk-vercel-ai-node"; // Create one Tilde client and reuse it wherever your agent needs tools. const tilde = createClient({ apiKey: process.env.TILDE_API_KEY!, orgId: process.env.TILDE_ORG_ID!, teamId: process.env.TILDE_TEAM_ID!, }); // Wherever your agent needs MCP tools, create the MCP client. const { mcp, closeMcp } = await createMCPClient({ client: tilde, serverId: process.env.TILDE_MCP_SERVER_ID!, }); // Pass `tools` to your model or agent runtime. const tools = await mcp.tools(); // Call `closeMcp()` after the agent finishes using the tools. await closeMcp(); ``` `createMCPClient` constructs the Tilde MCP endpoint and authenticates it with your Tilde API key. Keep the client open while the agent uses its tools, then call `closeMcp()`. Inside a ChatKit endpoint using `responseMode: "tool"`, call `context.session.createMCPClient({ serverId: process.env.TILDE_MCP_SERVER_ID! })` instead. The returned MCP client includes the current provider's session-bound communication tools, with channel, thread, participant, and recipient routing supplied by ChatKit rather than the model. Use `context.mcp.connect({ serverId })` when a shared ChatKit agent should apply the MCP server's personal-tool federation policy to the verified speaker. This connection forwards a private, invocation-scoped capability. Do not place that capability or a user/account identifier in tool arguments, messages, logs, or configuration. ## Add another Tilde agent as a tool Registering a ChatKit agent automatically creates a credentialless **Message agent** tool provider bound to it. Open the MCP server that your parent agent uses and add both generated tools: * `message` sends Vercel AI SDK-compatible message parts and immediately returns a ticket plus a ChatKit session ID. * `wait_for_response` subscribes to ChatKit in real time, emits the child response as MCP progress or logging notifications, and returns the persisted canonical ChatKit message when the turn finishes. Pass the previous session ID to `message` to continue a child conversation. The target agent's queue, interrupt, or queue-and-batch policy applies automatically. ## Connect a hosted MCP provider Open **Tools** → **Proxied MCP servers** → **Browse provider catalog** to connect a hosted MCP provider. The catalog includes ready-to-configure providers such as Notion, Granola, Browserbase, Parallel, Intercom, Zoom, Salesforce, Clay, Apollo, and HubSpot, alongside public documentation MCP servers. Tilde loads a reviewed tool-definition snapshot before you connect credentials, so the provider's tools can be inspected and selected in the same way as managed provider tools. After authentication, Tilde calls the upstream server's `tools/list` method and reconciles the deployed definitions with the live catalog. Providers are published in the connectable catalog only after a validated snapshot exists. The catalog records whether a snapshot came from an unauthenticated `tools/list` response, an official source repository, or official provider documentation. Definitions inferred from source or documentation are replaced by the authenticated upstream response as soon as the provider permits discovery. Authentication follows the upstream server: * OAuth providers use PKCE and published authorization metadata. Providers that support dynamic client registration create a new client for the current Tilde environment. * Manual OAuth providers ask for the provider's registered client ID and client secret. * API-key and bearer-token providers ask for the secret and the header or query-string placement required by the server. * Public documentation servers connect without credentials. OAuth tokens, client secrets, API keys, and bearer tokens are encrypted by Tilde's credential system. They are never stored in a tool definition or exported as plaintext state. ## Dynamic mode Dynamic mode exposes `SEARCH_TOOLS`, `GET_TOOL_SCHEMAS`, and `MULTI_EXECUTE_TOOL` instead of loading every tool schema into the model's context at once. The agent searches for relevant tools, loads only the schemas it needs, and can execute several tools together. We recommend enabling dynamic mode by default. It is especially useful when an MCP server contains many tools or its toolset changes frequently. Use static mode only for a small, fixed toolset where you want every tool to be immediately visible to the model. ## Remote custom tools Use a remote custom tool when the implementation should run independently from the agent and be reusable across multiple agents. Your server exposes a discovery manifest and an invocation endpoint. Tilde signs both requests with the custom tool provider's signing key. `toolEndpoint` exposes the discovery and invocation handlers, validates both Zod schemas, and verifies that every request came from Tilde. ```bash theme={"system"} pnpm add @trytilde/sdk-vercel-ai-node zod ``` ```typescript app/api/tools/route.ts theme={"system"} import { toolEndpoint } from "@trytilde/sdk-vercel-ai-node"; import { z } from "zod"; export const { GET, POST } = toolEndpoint({ webhookSigningKey: process.env.TILDE_CUSTOM_TOOL_SIGNING_KEY!, provider: { name: "Example tools", description: "Example remote tools", version: "1.0.0", }, tools: [ { id: "greet", name: "Greet", description: "Greet a person by name.", inputSchema: z.object({ name: z.string() }), outputSchema: z.object({ greeting: z.string() }), async fn({ name }) { return { greeting: `Hello, ${name}!` }; }, }, ], }); ``` Deploy the endpoint, then go to **Tools** → **Custom Tools** and choose **Remote HTTP server**. Enter the `GET /api/tools` URL as the discovery URL. Save the one-time signing key as `TILDE_CUSTOM_TOOL_SIGNING_KEY`, redeploy, then refresh the provider so Tilde can discover the manifest. By default, `toolEndpoint` derives the public invocation URL from the incoming request. If a proxy rewrites the public origin or path, set `baseUrl`, `endpointPath`, or both. ## Local custom tools Use a local custom tool when it needs in-process state, request context, or code that should not be deployed separately. Pass Vercel AI SDK tools to `createMCPClient`; they are returned alongside the tools from your Tilde MCP server. ```bash theme={"system"} pnpm add ai zod ``` ```typescript wherever-you-create-your-agent.ts theme={"system"} import { tool } from "ai"; import { z } from "zod"; import { createClient } from "@trytilde/sdk"; import { createMCPClient } from "@trytilde/sdk-vercel-ai-node"; const tilde = createClient({ apiKey: process.env.TILDE_API_KEY!, orgId: process.env.TILDE_ORG_ID!, teamId: process.env.TILDE_TEAM_ID!, }); const getReviewContext = tool({ description: "Return repository context available to this agent process.", inputSchema: z.object({ repository: z.string() }), outputSchema: z.object({ repository: z.string(), branch: z.string() }), async execute({ repository }) { return { repository, branch: process.env.GIT_BRANCH ?? "main" }; }, }); const { mcp, closeMcp } = await createMCPClient({ client: tilde, serverId: process.env.TILDE_MCP_SERVER_ID!, tools: { getReviewContext }, }); const tools = await mcp.tools(); // Keep the client open while the agent uses `tools`. await closeMcp(); ``` Local tools execute in the agent process. Their credentials and other sensitive inputs remain your responsibility. ## Reverse proxy Use a reverse proxy when your application or a third-party SDK needs the provider's native API instead of an MCP tool. Tilde injects the credential attached to the reverse-proxy profile, so the upstream credential does not need to enter your agent's environment. Reverse-proxy profiles have independent visibility and ownership. Visibility controls discovery and proxy invocation. Ownership controls the upstream URL, credential bindings, injected headers, enabled state, grants, and deletion. Seeing or invoking a profile never grants access to the credential's metadata, secret, or settings; the proxy receives only an exact internal consumption capability after profile authorization. The [code review bot](https://github.com/trytilde/examples/tree/main/code-review-bot) uses this pattern to clone repositories through a GitHub Git HTTPS profile and connect to Modal through a gRPC profile. ```typescript github-api.ts theme={"system"} import { createClient, reverseProxyPath } from "@trytilde/sdk"; const tilde = createClient({ apiKey: process.env.TILDE_API_KEY!, orgId: process.env.TILDE_ORG_ID!, teamId: process.env.TILDE_TEAM_ID!, }); const url = new URL( reverseProxyPath({ profileId: process.env.TILDE_GITHUB_PROXY_PROFILE_ID!, teamId: tilde.config.teamId, path: "repos/trytilde/examples/pulls/1", }), tilde.config.baseUrl, ); const response = await fetch(url, { headers: { "x-api-key": process.env.TILDE_API_KEY!, }, }); if (!response.ok) { throw new Error(`GitHub request failed: ${response.status}`); } const pullRequest = await response.json(); ``` Reverse proxies are enabled by default for supported tool providers. ## Personal OAuth through provider setup Applications can reuse the workspace provider catalog while creating an account owned by the signed-in user. Send `personal: true` to `POST /api/v1/team/{team_id}/provider-setup/start`, together with the catalog's provider and authentication method IDs. Use a distinct `form_values.id` for each account and supply `return_url` for the OAuth callback. Personal OAuth stores both the connection and its refreshable credential in the user scope. Tokens use the user's encryption key. Tilde ensures the owner's scoped key exists before OAuth starts and again when resuming a callback, including for accounts created before personal encryption was introduced. The callback preserves custom account labels alongside the provider's account identity. Read the resulting accounts from `/api/v1/user/{user_id}/mcp/tool-group`. Workspace-owned setup remains the default when `personal` is omitted. Agents use these accounts through session-bound personal tool federation rather than receiving credentials.