> ## Documentation Index
> Fetch the complete documentation index at: https://docs.useterse.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Overview

> Terse is the AI workflow platform for coding agents.

<CardGroup cols={2}>
  <Card title="Quickstart" icon="rocket" href="/quickstart">
    Get a workflow live in under 5 minutes.
  </Card>

  <Card title="Context as Code" icon="lightbulb" href="/context-as-code">
    How generated helpers make workflows more stable.
  </Card>
</CardGroup>

## Why Terse

Most AI workflows are easy to prototype and hard to keep running. An integration's schema drifts, a prompt quietly regresses, a step that called an LLM now needs a guardrail, and the agent that wrote the workflow can't fix it because it can't see the audit log.

Terse handles the long tail of that work in one place: a typed TypeScript SDK with deterministic **ACL guardrails** on every integration call (the Slack guardrail, for example, only lets the agent post in channels the workspace has explicitly approved), a sandboxed runtime you ship to with `terse deploy`, an audit log that unifies deterministic and agent steps, and agent skills (`terse-create`, `terse-improve`, `terse-self-host`) you install with `npx terse-cli install` so the coding agent in your editor can build and maintain workflows with you.

## What a workflow looks like

A Terse workflow is a single TypeScript file. Triggers come from your generated SDK, so the GitHub repo and Slack channel referenced below resolve to typed constants your editor can autocomplete. The agent receives **skills**, the scope contract for integration access, and the runtime refuses any tool call outside what those skills declare. Deterministic SDK calls and agent runs share one audit log.

The job below watches a repo for new pull requests, posts a deterministic Slack message announcing the PR, then threads a Block Kit summary under it:

```ts theme={null}
import { createJob, generateText } from "terse-sdk"

import { GithubPRTrigger, Repos, Skills, SlackChannel, Triggers, toolbox } from "../terse.generated"

// ^^ Generated based on your workspace

createJob({
    name: "Summarize PR and send slack message",
    triggers: [Triggers.github.onPROpened({ repo: Repos.TerseAI.Terse })],
    onTrigger: async (event: GithubPRTrigger) => {
        // Deterministic call — fixed channel, fixed message. No agent needed.
        const message = await toolbox.slack.sendMessage({
            channelId: SlackChannel.AllTerseInc.channelId,
            message: "New PR from " + event.sender.login + "!"
        })

        // Outputs are strongly typed
        const parentId = message.message_ts

        // Agentic: one prompt in, the model uses the GitHub + Slack tools granted via skills
        await generateText({
            prompt: `
            Summarize this PR ${event.formatForAgentRunner()}.
            Keep it short. Format the summary in Block Kit; include screenshots or diagrams from the PR as image blocks.
            Reply in a thread to the Slack message (thread parent ts: ${parentId}).
            `,
            skills: [
                // Fine tune what the agent has access to. Impossible to touch anything outside this scope
                Skills.github({ repos: [Repos.TerseAI.Terse] }),
                Skills.slack({ channel: SlackChannel.AllTerseInc })
            ]
        })
    }
})
```

The skills passed to `generateText` are the only surface the model can reach: it can post in one Slack channel and read this one repo, nothing else. The deterministic `toolbox.slack.sendMessage` call returns a typed result you can thread on directly, and `generateText` picks up the GitHub and Slack tools without further wiring.

## Supported integrations

export const GitHubIcon = <svg viewBox="0 0 24 24" fill="currentColor">
        <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" />
    </svg>;

export const SlackIcon = <svg viewBox="0 0 122.8 122.8">
        <path d="M25.8 77.6c0 7.1-5.8 12.9-12.9 12.9S0 84.7 0 77.6s5.8-12.9 12.9-12.9h12.9v12.9zm6.5 0c0-7.1 5.8-12.9 12.9-12.9s12.9 5.8 12.9 12.9v32.3c0 7.1-5.8 12.9-12.9 12.9s-12.9-5.8-12.9-12.9V77.6z" fill="#e01e5a" />
        <path d="M45.2 25.8c-7.1 0-12.9-5.8-12.9-12.9S38.1 0 45.2 0s12.9 5.8 12.9 12.9v12.9H45.2zm0 6.5c7.1 0 12.9 5.8 12.9 12.9s-5.8 12.9-12.9 12.9H12.9C5.8 58.1 0 52.3 0 45.2s5.8-12.9 12.9-12.9h32.3z" fill="#36c5f0" />
        <path d="M97 45.2c0-7.1 5.8-12.9 12.9-12.9s12.9 5.8 12.9 12.9-5.8 12.9-12.9 12.9H97V45.2zm-6.5 0c0 7.1-5.8 12.9-12.9 12.9s-12.9-5.8-12.9-12.9V12.9C64.7 5.8 70.5 0 77.6 0s12.9 5.8 12.9 12.9v32.3z" fill="#2eb67d" />
        <path d="M77.6 97c7.1 0 12.9 5.8 12.9 12.9s-5.8 12.9-12.9 12.9-12.9-5.8-12.9-12.9V97h12.9zm0-6.5c-7.1 0-12.9-5.8-12.9-12.9s5.8-12.9 12.9-12.9h32.3c7.1 0 12.9 5.8 12.9 12.9s-5.8 12.9-12.9 12.9H77.6z" fill="#ecb22e" />
    </svg>;

export const LinearIcon = <svg viewBox="0 0 100 100" fill="none">
        <path fill="#5E6AD2" d="M1.22541 61.5228c-.2225-.9485.90748-1.5459 1.59638-.857L39.3342 97.1782c.6889.6889.0915 1.8189-.857 1.5964C20.0515 94.4522 5.54779 79.9485 1.22541 61.5228ZM.00189135 46.8891c-.01764375.2833.08887215.5599.28957165.7606L52.3503 99.7085c.2007.2007.4773.3075.7606.2896 2.3692-.1476 4.6938-.46 6.9624-.9259.7645-.157 1.0301-1.0963.4782-1.6481L2.57595 39.4485c-.55186-.5519-1.49117-.2863-1.648174.4782-.465915 2.2686-.77832 4.5932-.92588465 6.9624ZM4.21093 29.7054c-.16649.3738-.08169.8106.20765 1.1l64.77602 64.776c.2894.2894.7262.3742 1.1.2077 1.7861-.7956 3.5171-1.6927 5.1855-2.684.5521-.328.6373-1.0867.1832-1.5407L8.43566 24.3367c-.45409-.4541-1.21271-.3689-1.54074.1832-.99132 1.6684-1.88843 3.3994-2.68399 5.1855ZM12.6587 18.074c-.3701-.3701-.393-.9637-.0443-1.3541C21.7795 6.45931 35.1114 0 49.9519 0 77.5927 0 100 22.4073 100 50.0481c0 14.8405-6.4593 28.1724-16.7199 37.3375-.3903.3487-.984.3258-1.3542-.0443L12.6587 18.074Z" />
    </svg>;

export const AttioIcon = <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 36.5 30">
        <path fill="currentColor" d="m35.705 20.45-3.014-4.778s-.011-.02-.018-.029l-.238-.375a2.44 2.44 0 0 0-2.072-1.142l-4.854-.015-.34.537-5.8 9.195-.32.509 2.43 3.846a2.43 2.43 0 0 0 2.079 1.142h6.803c.839 0 1.633-.438 2.077-1.14l.24-.38s.009-.01.01-.015l3.02-4.784a2.41 2.41 0 0 0 0-2.572zm-.92 2-3.018 4.784q-.021.032-.042.058a.41.41 0 0 1-.652-.06l-3.02-4.784a1.3 1.3 0 0 1-.154-.344 1.37 1.37 0 0 1 0-.737c.034-.118.085-.236.152-.342l3.014-4.78.007-.01a.38.38 0 0 1 .24-.172c.031-.009.058-.011.08-.015h.034c.07 0 .243.022.35.195l3.014 4.777a1.34 1.34 0 0 1 0 1.43zM26.786 8.89a2.42 2.42 0 0 0 0-2.572l-3.014-4.777-.251-.402A2.44 2.44 0 0 0 21.442 0H14.64c-.85 0-1.626.426-2.08 1.142L.378 20.452A2.4 2.4 0 0 0 0 21.738c0 .453.13.9.374 1.284l3.268 5.181a2.44 2.44 0 0 0 2.076 1.14h6.804c.854 0 1.63-.427 2.079-1.142l.248-.391v-.005s.005-.006.005-.008l2.429-3.847 7.198-11.409 2.3-3.649zm-.71-1.286c0 .247-.07.496-.212.715L13.93 27.237a.41.41 0 0 1-.35.19c-.07 0-.24-.02-.35-.19l-3.016-4.786a1.35 1.35 0 0 1 0-1.428L22.15 2.11a.41.41 0 0 1 .35-.193c.069 0 .242.02.352.195l3.013 4.777c.142.22.211.469.211.715" />
    </svg>;
export const ApolloIcon = <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
        <path fill="currentColor" fillRule="evenodd" d="M12 2 22 22h-4.4l-1.7-3.7H8.1L6.4 22H2L12 2Zm0 6.9-2.5 5.6h5L12 8.9Z" />
    </svg>;
export const WorkOSIcon = <svg viewBox="0 0 256 222" fill="none">
        <path d="M149.078 0C144.195 3.454 140.067 7.861 136.941 12.951L136.366 13.913L125.522 32.679L80.381 110.935L123.137 184.835L112.303 203.611C103.611 218.717 85.436 225.549 68.946 219.909C60.537 217.103 53.717 210.945 49.113 203.373L48.645 202.585L3.753 124.848C1.276 120.66 0 115.797 0 110.935C-0.009 106.354 1.13 101.849 3.305 97.828L3.753 97.031L49.921 17.065C55.844 6.72 66.757 0.284 78.653 0.009L79.448 0H149.078Z" fill="#6363F1" />
        <path d="M163.407 1.96C179.642-3.51 197.46 3.01 206.353 17.57L206.764 18.258L252.247 97.021C254.724 101.2 256 106.072 256 110.935C256 115.493 254.879 120.052 252.697 124.047L252.247 124.838L206.079 204.804C200.156 215.149 189.243 221.585 177.347 221.86L176.552 221.869H106.922C111.724 218.428 115.851 214.086 119.014 208.986L119.634 207.956L130.478 189.18L175.619 110.935L132.863 36.941L143.106 19.284C147.709 11.343 154.717 4.863 163.407 1.96Z" fill="#6363F1" />
    </svg>;

export const ResendIcon = <svg viewBox="0 0 24 24" fill="currentColor">
        <path d="M14.679 0c4.648 0 7.413 2.765 7.413 6.434s-2.765 6.434-7.413 6.434H12.33L24 24h-8.245l-8.88-8.44c-.636-.588-.93-1.273-.93-1.86 0-.831.587-1.565 1.713-1.883l4.574-1.224c1.737-.465 2.936-1.81 2.936-3.572 0-2.153-1.761-3.4-3.939-3.4H0V0z" />
    </svg>;

<CardGroup cols={4}>
  <Card title="GitHub" icon={GitHubIcon} />

  <Card title="Slack" icon={SlackIcon} />

  <Card title="Attio" icon={AttioIcon} />

  <Card title="Linear" icon={LinearIcon} />

  <Card title="Notion" icon="https://mintcdn.com/terse/QJxXNBQzMoUWeu_W/images/integrations/notion.png?fit=max&auto=format&n=QJxXNBQzMoUWeu_W&q=85&s=86d9155a38af51f60e3e03fc448f834d" width="96" height="96" data-path="images/integrations/notion.png" />

  <Card title="Snowflake" icon="https://mintcdn.com/terse/DYFm7KrHqTKQwqwJ/images/integrations/snowflake.png?fit=max&auto=format&n=DYFm7KrHqTKQwqwJ&q=85&s=d9136d4e8f9ebd3d9e0a50f3b007a987" width="306" height="306" data-path="images/integrations/snowflake.png" />

  <Card title="Gmail" icon="https://mintcdn.com/terse/QJxXNBQzMoUWeu_W/images/integrations/gmail.png?fit=max&auto=format&n=QJxXNBQzMoUWeu_W&q=85&s=940b3fe8dd8097a7914e151f8670c3f7" width="1024" height="768" data-path="images/integrations/gmail.png" />

  <Card title="Google Search Console" icon="https://mintcdn.com/terse/51vxJJk-zLO38DKJ/images/integrations/google-search-console.svg?fit=max&auto=format&n=51vxJJk-zLO38DKJ&q=85&s=a3b258b2efb1767daec1ea49df335f8f" width="278" height="40" data-path="images/integrations/google-search-console.svg" />

  <Card title="PostHog" icon="https://mintcdn.com/terse/DYFm7KrHqTKQwqwJ/images/integrations/posthog.png?fit=max&auto=format&n=DYFm7KrHqTKQwqwJ&q=85&s=5ca13bb8af96c1781221ea9284a53bd3" width="996" height="956" data-path="images/integrations/posthog.png" />

  <Card title="Datadog" icon="https://mintcdn.com/terse/QJxXNBQzMoUWeu_W/images/integrations/datadog.png?fit=max&auto=format&n=QJxXNBQzMoUWeu_W&q=85&s=de2e582d50c16cfa0bd69863a9300cc5" width="1600" height="1713" data-path="images/integrations/datadog.png" />

  <Card title="LaunchDarkly" icon="https://mintcdn.com/terse/QJxXNBQzMoUWeu_W/images/integrations/launchdarkly.jpeg?fit=max&auto=format&n=QJxXNBQzMoUWeu_W&q=85&s=684de3864f044769d756c943f72f921f" width="200" height="200" data-path="images/integrations/launchdarkly.jpeg" />

  <Card title="Apollo" icon={"/images/integrations/apollo.jpeg"} />

  <Card title="WorkOS" icon={WorkOSIcon} />

  <Card title="HeyReach" icon="https://mintcdn.com/terse/MyM_zZsnzX4Iu_5C/images/integrations/heyreach.png?fit=max&auto=format&n=MyM_zZsnzX4Iu_5C&q=85&s=c90ccc69dd3e9dca538d5ea57dfad01a" width="1559" height="1133" data-path="images/integrations/heyreach.png" />

  <Card title="Resend" icon={ResendIcon} />
</CardGroup>

## Start building

<CardGroup cols={2}>
  <Card title="Quickstart" icon="rocket" href="/quickstart">
    Install the CLI, generate your typed SDK, and deploy a workflow that runs on the next GitHub PR. Five minutes, end to end.
  </Card>

  <Card title="Jobs" icon="workflow" href="/core-concepts/jobs">
    How `createJob` ties triggers, handlers, and agents together. The primitive every workflow is built on.
  </Card>
</CardGroup>
