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

# Project automations

> Use remote MCP tools and start project agents from signed webhooks, REST or MCP.

An automation connects an incoming event to a project agent. It fixes the project,
instructions, model, allowed connections and execution limits. A connection supplies
external tools; a webhook supplies events. You can use either independently.

Open [Automations](https://editor.pascal.app/automations) in a workspace, or choose
**Automations → Set up** in project settings. Runs use the existing hosted agent runtime
and can continue without an editor tab.

## Configure an automation

Choose a project, describe the task, select an Architect effort or another available
model, and set credit, duration and delivery limits. Select only the connections the
task needs. Organization project automations require workspace-shared connections. Google
Drive accounts cannot be used by automations.

Each event starts a separate conversation owned by the automation creator. Its history
and result require that owner's current workspace and project access. Changes the run
makes to the project retain the project's normal visibility.

An accepted event pins the automation revision and model. Edits apply to future events.
Edits made in the browser keep the automation bound to the credential that created it; an
update made with an API key binds it to that key.
Pausing stops new admissions and revokes active runs at the next authority boundary.
Removing membership, revoking the original API key or disconnecting an account also
removes its authority. A browser-created automation does not depend on its browser
session staying alive.

The duration starts at acceptance and includes queue and question time. Automated runs
wait while another project agent is active. A test event is a paid run with the same limits.

> [!NOTE]
>
> Credit limits use Pascal's existing runtime. Non-Pro turns stop between model rounds,
> so the last round can exceed the threshold. Pro checks each model call against its
> budget; sandbox usage is settled separately and can take the total above it. External
> providers can charge separately. Daily admission reserves each accepted run's configured
> maximum for a rolling 24 hours, including failed and cancelled runs.

## REST setup

Use a workspace-scoped **human-script** API key from Settings. Agent keys and OAuth
scene grants cannot create persistent delegations or manage connection credentials.
The UI and API use the same command handler.

```ts theme={null}
const baseUrl = 'https://editor.pascal.app'
const workspaceId = 'organization:YOUR_ORGANIZATION_ID'
const authorization = 'Bearer ' + process.env.PASCAL_API_KEY

async function command(command) {
  const response = await fetch(baseUrl + '/api/workspace/automations', {
    method: 'POST',
    headers: { authorization, 'Content-Type': 'application/json' },
    body: JSON.stringify({ workspaceId, command }),
  })
  const result = await response.json()
  if (!response.ok) throw new Error(result.error)
  return result
}

const created = await command({
  action: 'create',
  specification: {
    name: 'Review incoming briefs',
    projectId: 'YOUR_PROJECT_ID',
    instructions: 'Review the brief and update the project. Ask if a requirement is unclear.',
    engine: { type: 'architect', effort: 'medium' },
    connectionIds: [],
    maxCredits: 50,
    maxDailyCredits: 200,
    maxRunsPerHour: 10,
    maxDurationSeconds: 900,
    eventType: 'brief.received',
    callbackUrl: 'https://your-app.example/pascal/completed',
    enabled: true,
  },
})
// Save created.secrets.webhook and created.secrets.callback in your secret store.
// Do not log them or send them to a model.
// created.automation.webhookPath identifies the incoming endpoint.
```

Use `engine: { type: 'model', modelId: '...' }` for another model returned by
`GET /api/workspace/automations?workspaceId=...`. Disabled or changed models are
refused; Pascal does not silently substitute another model.

Update with `action: 'update'`, the automation `id`, its current `revision`, and a
complete `specification`. A stale revision returns 409. Reveal signing secrets with
`action: 'reveal'`; add `rotate: true` to replace the incoming webhook secret.

## Send a signed event

The event contains `type`, optional ISO `time`, and JSON `data`, totaling at most
32 KB. Project, instructions and limits cannot be overridden by the event.

```ts theme={null}
import { createHmac, randomUUID } from 'node:crypto'

// Persist these together before sending. Reuse them on every retry of this event.
const eventId = randomUUID()
const body = JSON.stringify({
  type: 'brief.received',
  data: { brief: 'Add a meeting room near the entrance.' },
})

async function deliver() {
  const timestamp = String(Math.floor(Date.now() / 1000))
  const signature = 'v1=' + createHmac('sha256', process.env.PASCAL_WEBHOOK_SECRET)
    .update(timestamp + '.' + eventId + '.').update(body).digest('hex')
  const response = await fetch(process.env.PASCAL_WEBHOOK_URL, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Pascal-Event-Id': eventId,
      'X-Pascal-Timestamp': timestamp,
      'X-Pascal-Signature': signature,
    },
    body,
  })
  if (!response.ok) throw new Error('Delivery failed: ' + response.status)
  return response.json()
}
```

Signatures cover the exact bytes and must be within five minutes. Retries use a fresh
timestamp and signature with the original event ID and payload. A 202 response contains
`runId`, `duplicate` and an authenticated `statusUrl`. It confirms durable acceptance,
not successful execution.

One source event creates one run even with concurrent deliveries. A different payload
under an existing ID returns 409. A replay after an automation update returns the first
run and revision. A failed run is not automatically run again. A launch that fails before
the agent starts, for example while no executor is available, is retried on later ticks until
the deadline; a refusal such as a changed model fails the run.

## Inspect and control a run

Poll `GET /api/project-runs/{runId}` with the owner's current workspace credential.
States are `queued`, `running`, `waiting`, `completed`, `failed` and `cancelled`.
The response includes the canonical `responseId`, conversation identity, result,
saved-version and usage information when available, and callback delivery status.
Read large outputs through the existing `/v1/responses/{responseId}` API.

Cancel with `{ action: 'cancel', id: runId }`. Completed scene changes and external
actions are not undone. Answer a waiting question's returned `interactionId`:

```ts theme={null}
await command({
  action: 'answer',
  id: runId,
  interactionId: run.interactionId,
  idempotencyKey: answerId, // Keep this value when retrying the same answer.
  answer: 'Use the north wall.',
})
```

The answer resumes the same run and budget. It cannot answer a later question.
For a one-off run, use `action: 'run'` with `specification`, `event` and `eventId`,
without creating an automation. Direct REST and MCP runs share the event identity
within the owner/project; each saved automation has its own namespace. A direct run with
a callback returns `callbackSecret` to the authenticated REST caller, including when
replaying the same admission after a lost response.

## Receive completion events

An optional callback receives JSON with `id`, `source`, `type`, `time` and
`data`. Types are `project.run.completed`, `project.run.failed` and
`project.run.cancelled`; `data` contains the run result.

Verify the same signature headers against the **callback** secret, using the exact body
and a five-minute timestamp window. Record delivery IDs durably and acknowledge duplicates
with 2xx. Every retry uses the same ID and body with a fresh timestamp and signature.
Pascal makes up to six attempts, with delays of one minute, five minutes, 30 minutes,
two hours and 12 hours.

Callback retries only resend results. They never start the agent again. Delivery stops
if the owner loses access, the original credential is revoked, the automation is paused
or its callback destination changes. Callback URLs must be public HTTPS on port 443,
without credentials, query strings, fragments or redirects.

## MCP and discovery

The hosted inventory includes connection setup, tool approval, automation management,
and run start/inspect/cancel/answer operations. Management tools require a full-authority
human-script key. Secrets are omitted from model results; setup links to Pascal's UI.
Use a saved automation for callbacks configured through MCP, or retrieve a direct run's
signing key through an authenticated REST admission replay.

Discover approved custom tools with `list_connector_actions` and invoke them with
`call_connector_tool`, an explicit external-effect operation with an idempotency key.
The read-only `run_connector_action` path cannot invoke them. For
`operation_outcome_unknown`, inspect the external service before issuing a new key.

[OpenAPI](https://editor.pascal.app/api/openapi.json) and the
[MCP inventory](https://editor.pascal.app/.well-known/mcp) describe the supported operations.
Public discovery does not publish workspace connection details, automations or secrets.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.