Skip to main content

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.

Most automation platforms treat your workspace as runtime data: every execution rediscovers which channel is which, which list is which, which repo is which. That’s fragile for humans and invisible to coding agents. Terse inverts that. terse generate reads your connected integrations and compiles your workspace into typed code. Your workflows import real resources by name, and your coding agent (Cursor, Claude Code, Windsurf) sees the full surface as autocompletions and types.

The problem it solves

At runtime, without context-as-code, workflows rediscover the workspace on every execution:
const lists = await attio.lists.list()
const deals = lists.find(list => list.name === "New deals")

const channels = await slack.conversations.list()
const alertsChannel = channels.find(channel => channel.name === "deal-desk")

if (!deals || !alertsChannel) {
    throw new Error("Workspace context drifted")
}
This adds latency, wastes tokens, and silently breaks when someone renames a channel. At build time, coding agents have no idea what lives in your workspace. They guess at channel names, hallucinate list IDs, and produce workflows you have to manually correct. There’s no autocomplete, no type check, and no way for the agent to know what’s actually connected.

The idea

Compile your workspace into typed code once, then write workflows against it. Resource IDs become constants. Trigger builders and skills become namespaces. Tool wrappers become typed methods on agent.tools.*.
import { TerseAgent, createJob } from "terse-sdk"

import { Attio, AttioList, Slack, SlackChannel } from "./terse.generated"

createJob({
    name: "new-deal-enrichment",
    triggers: [Attio.onRecordCreated({ list: AttioList.Pipeline.NewDeals })],
    onTrigger: async event => {
        const agent = TerseAgent.create({
            prompt: "You enrich new deals and alert the deal desk.",
            skills: [Attio.skill({ lists: [AttioList.Pipeline.NewDeals] }), Slack.skill({ channel: SlackChannel.DealDesk })]
        })
        /* your logic */
    }
})
No runtime discovery. No hardcoded IDs. If an agent or a human references a resource that doesn’t exist in your workspace, the TypeScript compiler rejects it and terse deploy refuses to ship.

Where to go next

Generated SDK

The anatomy of terse.generated.ts, with samples of every export.

Quickstart

Get a workflow live in under 10 minutes.