Context Reference
Type calls a subscription method with two arguments: ctx and event. This page lists every property and method of ctx. For event, see the Events reference.
import type { AutomationContext, RecurringEvent,} from "@type-dot-com/sdk/automations";
export default class { daily(ctx: AutomationContext, event: RecurringEvent) { return ctx.setOutput({ ranAt: event.scheduledAt }); }}The type of ctx is AutomationContext. Import it from @type-dot-com/sdk/automations.
Rules for all methods
Section titled “Rules for all methods”- Methods that call Type return
ResultAsync<T, TypeApiError>fromneverthrow. They do not throw. CheckisErr()before you use the value. - A run can send at most 128 requests to Type. This count includes tool calls, reads, writes, messages, data reads, and searches.
- At most 8 requests can be in progress at the same time. Await calls, or limit
Promise.allto small groups. - Each response to a request can be at most 2 MiB. Ask for smaller pages if a response is larger.
- Each request body can be at most 1 MiB.
- Type does not retry a request automatically. If a write times out, the write can still be complete. Read the destination before you try again.
console.logdoes nothing. Usectx.setOutput()or action logs to see values in run history.
See Limits for all limits.
Summary
Section titled “Summary”| Member | Type | Use it to |
|---|---|---|
ctx.identity | AutomationExecutionIdentity | Read the IDs of this automation, run, and event. |
ctx.checkpoint | { value, version } | null | Read the state that the last successful run saved. |
ctx.saveCheckpoint() | (value) => Result<void> | Save state for the next run. |
ctx.setOutput() | (value) => Result<void> | Show a result in run history. |
ctx.setSummary() | (text) => Result<void> | Show one sentence about what the run did. |
ctx.setVisualization() | (value) => Result<void> | Save a report of the results. Needs reports to be on. |
ctx.tools | Tool client | Find and call integration tools and sandbox commands. |
ctx.read | Read client | Read tool data, API data, saved data, and search results. |
ctx.write | Write client | Change data in a connected app, or post in a Space. |
ctx.agent | Agent client | Give work that needs judgment to the managed agent. |
ctx.action() | Action logger | Record an important step in run history. |
ctx.mutativeAction() | Action logger | Record a step that changes data. |
ctx.jev | AutomationJevResult | null | Read answers to AI questions about the event. |
ctx.signal | AbortSignal | Stop work when the run deadline comes. |
ctx.identity
Section titled “ctx.identity”Read-only IDs for the current run.
| Field | Type | Meaning |
|---|---|---|
organizationId | string | The workspace that owns the automation. |
automationId | string | The automation. |
revisionId | string | The saved code revision that runs now. |
runId | string | This run. |
subscriptionId | string | The subscription key, which is also the method name. |
eventId | string | The event that started this run. |
purpose | "live" | "test" | "repair" | Why Type started the run. |
phase | "subscription" | "inspect" | "execute" | The run phase. Methods always get "execute". |
These IDs are information only. Type does not use them to give access. Type checks access with a short-lived token for each run.
ctx.checkpoint
Section titled “ctx.checkpoint”The state that the last successful run of this subscription saved. The value is null before the first successful save.
interface AutomationCheckpoint { readonly value: JsonValue; readonly version: string;}- Each subscription has its own checkpoint. Two subscriptions in the same automation do not share it.
- The checkpoint stays when you deploy new code, if the subscription key stays the same.
- If you rename a subscription key, the new key starts with no checkpoint.
ctx.saveCheckpoint()
Section titled “ctx.saveCheckpoint()”saveCheckpoint(value: JsonValue): Result<void, TypeApiError>Saves value as the next checkpoint for this subscription.
- The value must be JSON.
- Type saves the checkpoint only when the method succeeds. If the run fails, the old checkpoint stays.
- If you call it more than one time, the last value is saved.
- The call is synchronous. It returns a
Result, not aResultAsync. - If the value is not JSON, the run fails, even if your code ignores the error.
ctx.setOutput()
Section titled “ctx.setOutput()”setOutput(value: JsonValue): Result<void, TypeApiError>Sets the result that run history shows for this run. It does not post a message and does not start a conversation.
- The value must be JSON. Keep it small. All results of a run must fit in 2 MiB of JSON together: the output, checkpoint, report, handoffs, and action logs. Type does not cut a large result. It fails the run.
- If you call it more than one time, the last value is kept.
- Fixtures compare
expectedOutputwith this value. - A common pattern is
return ctx.setOutput({ ... })at the end of the method.
ctx.setSummary()
Section titled “ctx.setSummary()”setSummary(value: string): Result<void, TypeApiError>Sets one plain sentence that says what this run did. An example is “Two tickets arrived; one is about billing.” Type shows it as the headline of the run in run history, and under the report.
- The text must be 1 to 300 characters after Type trims spaces. Otherwise the run fails.
- Describe the change, not the steps of the code.
- Do not set a summary for a run that did nothing.
ctx.setVisualization()
Section titled “ctx.setVisualization()”setVisualization(value: JsonValue): Result<void, TypeApiError>Saves a report for the automation, for example a chart, a table, or metric cards. The report shows on the automation page. The value is a json-render spec: { root, elements, state }.
- Set a report only when it helps people understand the results. Do not save a placeholder.
null, or no call, keeps the current report.ctx.setOutput()never makes a report.- The report shares the 2 MiB result limit.
- If the report is not valid, Type keeps the earlier report and records a warning. The run still succeeds.
- Test and repair runs do not change the live report.
- Saving a report does not send it anywhere.
- Limits: charts have at most 500 points and 12 series. A report has at most 200 elements after Type expands repeats.
ctx.tools
Section titled “ctx.tools”The integration tool client. Type checks the automation’s access on every call.
| Method | Returns | Use it to |
|---|---|---|
services(options?) | { services } | List the services that the automation can use. |
find({ service, organizationIntegrationId?, includeRelatedConnections? }, options?) | Tool list | Get tool names and input schemas for a service. |
call(call, options?) | ToolResult | Call a tool and get the raw result. |
callWithSchema(call, schema, options?) | ToolResult with parsed structuredContent | Call a tool and parse its structured result. |
A call object has these fields:
interface ToolCall { service: string; // for example "slack" or "managed-sandbox" name: string; // the tool name from find() arguments?: Record<string, JsonValue>; organizationIntegrationId?: string; // the connection ID, "orgint_..." rawSlug?: string;}A ToolResult has this shape:
interface ToolResult { content: Array<{ type: string; text?: string }>; structuredContent?: unknown; isError?: boolean;}Sandbox commands use ctx.tools.call with service: "managed-sandbox". They need an automationEffectKey option. See Run Commands in the Sandbox.
ctx.read
Section titled “ctx.read”Reads data. Use ctx.read only for operations that do not change data.
ctx.read.call()
Section titled “ctx.read.call()”call<S extends z.ZodType>(call: ToolCall, schema: S, options?: RequestOptions): ResultAsync<z.output<S>, TypeApiError>Calls a tool, then parses its structuredContent with your Zod schema. It returns the parsed value.
- It fails if the tool returns
isError: true. - It fails if
structuredContentdoes not match the schema. - JSON text in
content[].textis notstructuredContent. For tools that return only text, usectx.tools.call.
ctx.read.request()
Section titled “ctx.read.request()”request<S extends z.ZodType>(request: IntegrationRequest, schema: S, options?: RequestOptions): ResultAsync<z.output<S>, TypeApiError>Sends an HTTP request to a Custom API connection. Type adds the credentials. Your code never sees them. It parses the response body with your schema and returns the parsed value.
interface IntegrationRequest { organizationIntegrationId: string; method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE"; path: string; // relative to the connection's base URL query?: Record<string, string | number | boolean>; headers?: Record<string, string>; body?: JsonValue;}It fails if the response is not successful, if Type truncated the response, or if the body does not match the schema.
ctx.read.data
Section titled “ctx.read.data”Reads saved data for this automation.
| Method | Returns |
|---|---|
read(key, scope?, options?) | { found: true, key, value, version, updatedAt } or { found: false, key, version: null } |
list({ after?, limit? }, options?) | { items: [{ key, version, updatedAt }], nextCursor } |
Automation code cannot write saved data. Use checkpoints for state between runs.
ctx.read.search
Section titled “ctx.read.search”Searches the Type workspace.
| Method | Use it to |
|---|---|
workspace(query, options?) | Search people, Spaces, docs, apps, files, threads, and messages. |
messages({ query?, channelIds?, limit?, from?, to? }, options?) | Search messages, with optional channel and date filters. |
ctx.write
Section titled “ctx.write”Changes data. Each method needs an effectKey.
interface AutomationMutationOptions { effectKey: string; // stable for the same logical change, across retries and runs signal?: AbortSignal; timeoutMs?: number;}| Method | Use it to |
|---|---|
call(call, schema, { effectKey }) | Call a tool that changes data, then parse its structuredContent. |
request(request, schema, { effectKey }) | Send an HTTP request that changes data to a Custom API connection, then parse the body. |
sendMessage({ channelId, content, parentMessageId? }, { effectKey }) | Post a message in the automation’s Space. Set channelId to the Space ID (ch_...). Set parentMessageId to reply in a thread. Returns { messageId }. |
Only live runs get real writes. In a test, Type gives your code the responses from your fixtures.
ctx.agent
Section titled “ctx.agent”Gives work to the managed agent after your method succeeds. The deployment must use mode: "code_with_optional_agent". In mode: "code", these calls fail the run.
ctx.agent.run()
Section titled “ctx.agent.run()”run(input: { effectKey: string; // 1 to 500 characters instructions: string; // 1 to 10,000 characters context?: JsonValue; // evidence for the AI; default null tools?: Array<{ service: string; name: string; organizationIntegrationId: string; rawSlug?: string }>; // at most 16}): ResultAsync<void, TypeApiError>Stages a handoff. Type starts the AI only after the method succeeds. Type gives the AI the full source event. Use context for more evidence.
ctx.agent.evaluate()
Section titled “ctx.agent.evaluate()”evaluate(input: { effectKey: string; instructions: string; context?: JsonValue; tools?: AgentTool[]; evaluation: { question: string; // 1 to 2,000 characters criteria: { skip: string; // 1 to 2,000 characters invoke_agent: string; // 1 to 2,000 characters }; };}): ResultAsync<void, TypeApiError>Stages a handoff that Type evaluates first. After the method succeeds, Type asks a model if the work needs the AI.
- If the model answers
skipwith a confidence of 0.8 or more, no AI starts. - In all other cases, the AI starts. This includes a low-confidence answer, a failed evaluation, and a workspace with no evaluation model.
evaluate is not a synchronous classifier: your code does not get the answer. To get answers in code, use AI questions in a matcher.
Rules for both methods:
- A run can stage at most 100 handoffs.
- If you stage the same
effectKeywith the same input two times, Type keeps one handoff. - If you stage the same
effectKeywith different input, the run fails. - A staged handoff is not a delivered message. If the method fails, Type starts no handoffs.
See Hand Off Work to a Managed Agent.
ctx.action() and ctx.mutativeAction()
Section titled “ctx.action() and ctx.mutativeAction()”type Action = <T>( run: () => Result<T, TypeApiError> | ResultAsync<T, TypeApiError>, before: { id: string; message: string; data?: JsonValue }, after: (result: T) => { message: string; data?: JsonValue },) => ResultAsync<T, TypeApiError>;Records an important step in run history. Type saves the before log, runs run, then saves the after log.
- Use
mutativeActionfor steps that change data. Useactionfor other important steps. idmust be unique in the run, and 1 to 200 characters. It must not start or end with a space.messagemust be 1 to 2,000 characters. Each log must fit in 8 KiB.- A run can record at most 100 actions.
- If
runfails, Type records a failed step and returns the error. - If Type cannot save the
afterlog, the call fails with “Do not repeat the action”. The step itself can be complete.
Action logs do not retry, and they do not undo earlier changes. ctx.destructiveAction is an old name for ctx.mutativeAction. Do not use it in new code.
const created = await ctx.mutativeAction( () => ctx.write.call(createIssue, issueSchema, { effectKey: `issue:${event.id}` }), { id: "create-issue", message: `Create an issue for ${event.id}` }, (issue) => ({ message: `Created issue ${issue.id}`, data: { id: issue.id } }),);if (created.isErr()) return err(created.error);ctx.jev
Section titled “ctx.jev”Answers to the AI questions that the subscription’s matcher asked about this event. The value is null when the matcher asks no questions.
interface AutomationJevResult { model: string; answers: Record<string, JevAnswer>; // keyed by your question IDs}Each answer has the type of its question: noul (a probability from 0 to 1), choice, or score. See Filter Events with AI Questions.
ctx.signal
Section titled “ctx.signal”An AbortSignal that aborts when the run deadline comes. Pass it to long operations as the signal option.
Method return values
Section titled “Method return values”A subscription method can return:
- nothing, or a
Promiseof nothing, ok(undefined)orerr(error)fromneverthrow,- a
ResultAsync<void, TypeApiError>.
Return err(error) to fail the run. Do not throw. If the method throws, the run also fails, but the error is less clear.
import { TypeApiError } from "@type-dot-com/sdk";import { err } from "neverthrow";
return err(new TypeApiError("The order has no ID", "invalid_response"));