Connector Reference
Connectors define the actions a step can perform. Actions use a connector/action naming convention. For AI tool use (function calling), see Tool Use.
http/request
Makes an HTTP request.
Params:
| Param | Type | Required | Description |
|---|---|---|---|
method | string | Yes | HTTP method: GET, POST, PUT, PATCH, DELETE. |
url | string | Yes | Request URL. |
headers | map | No | HTTP headers as key-value pairs. |
body | any | No | Request body. Objects are JSON-encoded. |
Output:
| Field | Type | Description |
|---|---|---|
status | number | HTTP response status code. |
headers | map | Response headers. |
body | string | Raw response body as a string. |
json | any | Parsed response body. Only present when the response is valid JSON. |
Example:
- name: create-item
action: http/request
params:
method: POST
url: https://api.example.com/items
headers:
Authorization: "Bearer {{ env.API_TOKEN }}"
Content-Type: application/json
body:
name: "New Item"
quantity: 5
ai/completion
Sends a prompt to an OpenAI-compatible chat completion API and returns the result. Requires a credential with an API key — see the Secrets Guide for setup.
Params:
| Param | Type | Required | Description |
|---|---|---|---|
provider | string | No | AI provider to use: openai (default) or bedrock. |
model | string | Yes | Model name (e.g., gpt-4o, gpt-4o-mini, anthropic.claude-3-sonnet-20240229-v1:0). |
prompt | string | Yes | The user prompt to send. |
region | string | No | AWS region for the Bedrock provider (e.g., us-east-1). Only used when provider is bedrock. |
system_prompt | string | No | System message prepended to the conversation. |
output_schema | object | No | JSON Schema for structured output. When set, the model returns JSON conforming to this schema. |
base_url | string | No | Override the API base URL. Defaults to https://api.openai.com/v1. Use this for OpenAI-compatible providers like Azure, Ollama, or local models. |
tools | list | No | Tool declarations for function calling. See Tool Use. |
max_tool_rounds | integer | No | Maximum number of LLM-tool interaction rounds. Default: 10 (from engine.default_max_tool_rounds). |
max_tool_calls_per_round | integer | No | Maximum number of tool calls the LLM can make in a single round. Default: 10 (from engine.default_max_tool_calls_per_round). |
Output:
| Field | Type | Description |
|---|---|---|
text | string | The raw completion text returned by the model. |
json | any | If the response is valid JSON (e.g., from structured output), the parsed object. Only present when the response parses as JSON. |
tool_calls | list | Tool invocations requested by the model. Each item has id, type, and function (with name and arguments). Only present when the model requests tool calls in the final response. |
finish_reason | string | Why the model stopped generating. stop for normal text completion, tool_calls when the model requested tool invocations. |
model | string | The model name as reported by the API. |
usage.prompt_tokens | number | Number of tokens in the prompt. |
usage.completion_tokens | number | Number of tokens in the completion. |
usage.total_tokens | number | Total tokens used. |
Example — basic completion:
- name: summarize
action: ai/completion
credential: my-openai
params:
model: gpt-4o
prompt: "Summarize this in 3 bullet points: {{ steps.fetch-data.output.body }}"
Example — with system prompt and structured output:
- name: extract-entities
action: ai/completion
credential: my-openai
timeout: 60s
params:
model: gpt-4o
system_prompt: "You are a data extraction assistant. Always respond with valid JSON."
prompt: "Extract all person names and companies from: {{ steps.fetch-data.output.body }}"
output_schema:
type: object
properties:
people:
type: array
items:
type: string
companies:
type: array
items:
type: string
required:
- people
- companies
additionalProperties: false
The structured output is available as steps.extract-entities.output.json.people and steps.extract-entities.output.json.companies in subsequent steps.
Example — custom base URL (Ollama):
- name: local-completion
action: ai/completion
params:
model: llama3
base_url: http://localhost:11434/v1
prompt: "Explain this error: {{ steps.fetch-logs.output.body }}"
Example — AWS Bedrock:
- name: summarize
action: ai/completion
credential: aws-bedrock-creds
params:
provider: bedrock
model: anthropic.claude-3-sonnet-20240229-v1:0
region: us-east-1
prompt: "Summarize: {{ steps.fetch.output.body }}"
When running on AWS infrastructure with an IAM role attached (IRSA, instance profile, etc.), the credential field can be omitted — the Bedrock provider uses the standard AWS credential chain automatically.
Authentication: The AI connector reads the credential’s api_key field (or token or key as fallbacks) and sends it as a Bearer token. If the credential includes an org_id field, it is sent as the OpenAI-Organization header. See the Secrets Guide for how to create an openai-type credential.
slack/send
Sends a message to a Slack channel via the chat.postMessage API. Requires a credential with a Slack Bot User OAuth Token.
Params:
| Param | Type | Required | Description |
|---|---|---|---|
channel | string | Yes | Slack channel — either a channel ID (e.g., C01234ABCDE) or a channel name with # prefix (e.g., #general). Channel IDs are preferred for reliability. |
text | string | Yes | Message text. Supports Slack mrkdwn formatting. |
Output:
| Field | Type | Description |
|---|---|---|
ok | boolean | true if the message was sent successfully. |
ts | string | Slack message timestamp. Use this to reference the message in follow-up API calls. |
channel | string | The channel ID where the message was posted. |
Example:
- name: notify-team
action: slack/send
credential: slack-bot
params:
channel: "C01234ABCDE"
text: "Deployment complete: {{ steps.deploy.output.body }}"
Authentication: The Slack connector reads the credential’s token field and sends it as a Bearer token. Create a credential of type bearer with a token field containing your Slack Bot User OAuth Token:
mantle secrets create --name slack-bot --type bearer --field token=xoxb-your-bot-token
slack/history
Reads recent messages from a Slack channel via the conversations.history API.
Params:
| Param | Type | Required | Description |
|---|---|---|---|
channel | string | Yes | Slack channel ID (e.g., C01234ABCDE). |
limit | number | No | Maximum number of messages to return. Default: 10. |
Output:
| Field | Type | Description |
|---|---|---|
ok | boolean | true if the request was successful. |
messages | list | Array of message objects. Each message contains fields like text, user, ts, and type. |
Example:
- name: read-channel
action: slack/history
credential: slack-bot
params:
channel: "C01234ABCDE"
limit: 5
- name: summarize-messages
action: ai/completion
credential: my-openai
params:
model: gpt-4o
prompt: "Summarize these Slack messages: {{ steps['read-channel'].output.messages }}"
postgres/query
Executes a parameterized SQL query against an external Postgres database. The connector opens a connection per step execution and closes it afterward. Supports both read queries (SELECT, WITH) and write statements (INSERT, UPDATE, DELETE).
Params:
| Param | Type | Required | Description |
|---|---|---|---|
query | string | Yes | SQL query to execute. Use $1, $2, etc. for parameterized values. |
args | list | No | Ordered list of values to substitute into the parameterized query. |
Output (SELECT/WITH queries):
| Field | Type | Description |
|---|---|---|
rows | list | Array of row objects, each mapping column names to values. Empty array if no rows match. |
row_count | number | Number of rows returned. |
Output (INSERT/UPDATE/DELETE statements):
| Field | Type | Description |
|---|---|---|
rows_affected | number | Number of rows affected by the statement. |
Example — read query:
- name: fetch-users
action: postgres/query
credential: my-database
params:
query: "SELECT id, email FROM users WHERE active = $1 LIMIT $2"
args:
- true
- 100
Example — write statement:
- name: update-status
action: postgres/query
credential: my-database
params:
query: "UPDATE orders SET status = $1 WHERE id = $2"
args:
- "shipped"
- "{{ steps['create-order'].output.json.order_id }}"
Authentication: The Postgres connector reads the database connection URL from the credential’s url field (or key as a fallback). Create a credential with the full Postgres connection string:
mantle secrets create --name my-database --type generic --field url=postgres://user:pass@host:5432/dbname?sslmode=require
email/send
Sends an email via SMTP. Supports plaintext and HTML content.
Params:
| Param | Type | Required | Description |
|---|---|---|---|
to | string or list | Yes | Recipient email address(es). A single string or a list of strings. |
from | string | Yes | Sender email address. |
subject | string | Yes | Email subject line. |
body | string | Yes | Email body content. |
html | boolean | No | Set to true to send the body as HTML. Default: false (plaintext). |
smtp_host | string | No | SMTP server hostname. Can also be provided via credential. |
smtp_port | string | No | SMTP server port. Default: 587. Can also be provided via credential. |
Output:
| Field | Type | Description |
|---|---|---|
sent | boolean | true if the email was sent successfully. |
to | string | Comma-separated list of recipient addresses. |
subject | string | The subject line that was sent. |
Example:
- name: send-report
action: email/send
credential: smtp-creds
params:
to:
- "alice@example.com"
- "bob@example.com"
from: "reports@example.com"
subject: "Daily Report — {{ steps.generate.output.json.date }}"
body: "{{ steps.generate.output.json.html_report }}"
html: true
Authentication: The email connector reads username, password, host, and port from the credential. If host or port are not in the credential, they fall back to the smtp_host and smtp_port params. Create a basic credential with SMTP fields:
mantle secrets create --name smtp-creds --type basic \
--field username=apikey \
--field password=SG.your-sendgrid-key \
--field host=smtp.sendgrid.net \
--field port=587
email/receive
Reads messages from an email mailbox. Supports filtering by folder and read status.
Params:
| Param | Type | Required | Description |
|---|---|---|---|
folder | string | No | Folder to read from (e.g., INBOX, Archive, [Gmail]/Sent Mail). Default: INBOX. |
filter | string | No | Filter messages by status: all, unseen, recent, flagged. Default: unseen. |
limit | number | No | Maximum number of messages to return. Default: 10. |
mark_seen | boolean | No | Mark retrieved messages as seen. Default: false. |
Output:
| Field | Type | Description |
|---|---|---|
message_count | number | Number of messages returned. |
messages | array | Array of message objects. Each message contains: message_id (string), from (string), to (string), cc (string), subject (string), body (string), date (RFC 3339 timestamp), headers (map), flags (array of strings), uid (number, IMAP UID). |
Authentication: Credentials are provided via the step-level credential field. The email connector reads username, password, host, and port from the credential (IMAP-compatible).
Example:
- name: read-inbox
action: email/receive
credential: company-inbox
params:
folder: INBOX
filter: unseen
limit: 20
mark_seen: true
email/move
Moves an email message to a different folder.
Params:
| Param | Type | Required | Description |
|---|---|---|---|
uid | number | Yes | IMAP UID of the message. |
source_folder | string | No | Source folder (for reference). Default: INBOX. |
target_folder | string | Yes | Destination folder path (e.g., Archive, [Gmail]/All Mail). |
Output:
| Field | Type | Description |
|---|---|---|
moved | boolean | true if the move was successful. |
uid | number | The IMAP UID of the moved message. |
target_folder | string | The folder the message was moved to. |
Authentication: Credentials are provided via the step-level credential field.
Note: Gmail’s “archive” action is implemented as a move to [Gmail]/All Mail.
Example:
- name: archive-message
action: email/move
credential: company-inbox
params:
uid: "{{ trigger.uid }}"
source_folder: INBOX
target_folder: Archive
email/delete
Deletes an email message.
Params:
| Param | Type | Required | Description |
|---|---|---|---|
uid | number | Yes | IMAP UID of the message. |
folder | string | No | Folder containing the message. Default: INBOX. |
Output:
| Field | Type | Description |
|---|---|---|
deleted | boolean | true if the deletion was successful. |
uid | number | The IMAP UID of the deleted message. |
Authentication: Credentials are provided via the step-level credential field.
Example:
- name: delete-spam
action: email/delete
credential: company-inbox
params:
uid: "{{ trigger.uid }}"
folder: INBOX
email/flag
Adds or removes flags (labels) on an email message.
Params:
| Param | Type | Required | Description |
|---|---|---|---|
uid | number | Yes | IMAP UID of the message. |
flags | array | Yes | List of flag names to modify (e.g., ["flagged", "important"]). |
action | string | Yes | add to set flags, remove to unset flags. |
folder | string | No | Folder containing the message. Default: INBOX. |
Standard IMAP Flags:
| Flag | Description |
|---|---|
seen | Message has been read. |
flagged | Message is flagged for follow-up. |
answered | Message has been replied to. |
deleted | Message is marked for deletion. |
draft | Message is a draft. |
Custom Keywords: Most email providers support custom flag names beyond the standard set. These are often used as tags or labels (e.g., important, urgent, client-xyz).
Output:
| Field | Type | Description |
|---|---|---|
updated | boolean | true if the flag operation was successful. |
action | string | The operation performed: add or remove. |
uid | number | The IMAP UID of the message. |
flags | array | The flags that were modified. |
Authentication: Credentials are provided via the step-level credential field.
Example:
- name: flag-important
action: email/flag
credential: company-inbox
params:
uid: "{{ trigger.uid }}"
flags: ["flagged", "important"]
action: add
s3/put
Uploads an object to an S3-compatible storage bucket.
Params:
| Param | Type | Required | Description |
|---|---|---|---|
bucket | string | Yes | S3 bucket name. |
key | string | Yes | Object key (path) within the bucket. |
content | string | Yes | Object content as a string. |
content_type | string | No | MIME type for the object. Default: application/octet-stream. |
Output:
| Field | Type | Description |
|---|---|---|
bucket | string | The bucket the object was uploaded to. |
key | string | The object key. |
size | number | Size of the uploaded content in bytes. |
Example:
- name: upload-report
action: s3/put
credential: aws-s3
params:
bucket: "my-reports"
key: "reports/{{ steps.generate.output.json.date }}.json"
content: "{{ steps.generate.output.json.report }}"
content_type: "application/json"
s3/get
Downloads an object from an S3-compatible storage bucket.
Params:
| Param | Type | Required | Description |
|---|---|---|---|
bucket | string | Yes | S3 bucket name. |
key | string | Yes | Object key (path) within the bucket. |
Output:
| Field | Type | Description |
|---|---|---|
bucket | string | The bucket the object was downloaded from. |
key | string | The object key. |
content | string | Object content as a string. |
size | number | Size of the downloaded content in bytes. |
content_type | string | MIME type of the object as reported by S3. |
Example:
- name: download-config
action: s3/get
credential: aws-s3
params:
bucket: "my-configs"
key: "app/config.json"
s3/list
Lists objects in an S3-compatible storage bucket, with optional prefix filtering.
Params:
| Param | Type | Required | Description |
|---|---|---|---|
bucket | string | Yes | S3 bucket name. |
prefix | string | No | Filter results to keys that start with this prefix. |
Output:
| Field | Type | Description |
|---|---|---|
bucket | string | The bucket that was listed. |
objects | list | Array of objects. Each object has key (string), size (number), and last_modified (string, RFC 3339). |
Example:
- name: list-reports
action: s3/list
credential: aws-s3
params:
bucket: "my-reports"
prefix: "reports/2026/"
S3 Authentication
All S3 connectors (s3/put, s3/get, s3/list) read the following fields from the credential:
| Field | Required | Description |
|---|---|---|
access_key | Yes | AWS access key ID. |
secret_key | Yes | AWS secret access key. |
region | No | AWS region. Default: us-east-1. |
endpoint | No | Custom S3 endpoint URL. Use this for S3-compatible services like MinIO, DigitalOcean Spaces, or Backblaze B2. |
Create a credential for S3:
mantle secrets create --name aws-s3 --type generic \
--field access_key=AKIA... \
--field secret_key=wJalr... \
--field region=us-west-2
For S3-compatible services, add an endpoint field:
mantle secrets create --name minio --type generic \
--field access_key=minioadmin \
--field secret_key=minioadmin \
--field endpoint=http://localhost:9000
docker/run
Runs a Docker container to completion and captures its output. The container is created, started, waited on, and optionally removed. Non-zero exit codes do not constitute a step failure — use if conditions to branch on exit code.
Params:
| Param | Type | Required | Default | Description |
|---|---|---|---|---|
image | string | Yes | — | Container image (e.g., alpine:latest) |
cmd | array | No | — | Command and arguments |
env | object | No | — | Environment variables |
stdin | string | No | — | Data piped to container stdin |
mounts | array | No | — | Volume/bind mounts (each with source, target, readonly) |
network | string | No | bridge | Docker network mode (bridge or none) |
pull | string | No | missing | Image pull policy: always, missing, never |
memory | string | No | — | Memory limit (e.g., 512m, 1g) |
cpus | number | No | — | CPU limit (e.g., 1.5) |
remove | boolean | No | true | Remove container after completion |
Output:
| Field | Type | Description |
|---|---|---|
exit_code | integer | Container exit code |
stdout | string | Container stdout (capped at 10MB) |
stderr | string | Container stderr (capped at 10MB) |
Authentication: The Docker connector uses a docker credential type for daemon access. All fields are optional — an empty credential connects to the local Docker socket. For private images, use registry_credential with a basic credential type. Note that registry_credential is a step-level field (alongside credential), not a param.
Security: Containers run with all Linux capabilities dropped (CAP_DROP ALL), no-new-privileges, and a PID limit. Only bridge and none network modes are permitted.
Example:
- name: process-data
action: docker/run
credential: my-docker
registry_credential: my-registry
timeout: "2m"
params:
image: myorg/processor:latest
cmd: ["process", "--format", "json"]
stdin: "{{ steps['fetch-data'].output.body }}"
memory: "512m"
cpus: 1.0
browser/run
Runs browser automation scripts (JavaScript, TypeScript, or Python) using Playwright. Scripts run in a containerized browser environment and can interact with web pages, perform DOM queries, take screenshots, and generate structured output.
Params:
| Param | Type | Required | Default | Description |
|---|---|---|---|---|
language | string | No | javascript | Script language: javascript, typescript, or python. |
script | string | Yes | — | Browser automation script. The global browser object is a Playwright Browser instance. |
output_format | string | No | text | Output format: json or text. JSON output is automatically parsed. |
env | object | No | — | Environment variables accessible in the script via process.env (JS/TS) or os.environ (Python). |
pull | string | No | missing | Image pull policy: always, missing, never. |
memory | string | No | 1g | Memory limit (e.g., 512m, 1g). |
Output:
| Field | Type | Description |
|---|---|---|
exit_code | integer | Script exit code (0 = success). |
stdout | string | Script stdout output (capped at 10MB). |
stderr | string | Script stderr output (capped at 10MB). |
json | any | Parsed JSON output. Only present when output_format: json and stdout is valid JSON. |
Container Images:
- JavaScript/TypeScript:
mcr.microsoft.com/playwright:v1.52.0-noble - Python:
mcr.microsoft.com/playwright/python:v1.52.0-noble
Artifacts: Scripts can write files to /mantle/artifacts/ directory for screenshots, PDFs, HAR files, and other outputs. Declare artifacts in the step to register them with the execution.
Credentials: Secrets are injected as environment variables via the env param. Access them in scripts using process.env.VAR_NAME (JS/TS) or os.environ['VAR_NAME'] (Python).
Security: Containers run with all Linux capabilities dropped (CAP_DROP ALL), no-new-privileges, and a PID limit. Same security hardening as docker/run.
Example — JavaScript with login and screenshot:
- name: scrape-portal
action: browser/run
timeout: "2m"
params:
language: javascript
output_format: json
env:
USERNAME: "{{ inputs.username }}"
PASSWORD: "{{ inputs.password }}"
script: |
const page = await browser.newPage();
await page.goto('https://portal.example.com/login');
await page.fill('#username', process.env.USERNAME);
await page.fill('#password', process.env.PASSWORD);
await page.click('#login-button');
await page.waitForSelector('.dashboard');
const data = await page.evaluate(() => {
const rows = document.querySelectorAll('.data-table tr');
return Array.from(rows).map(row => ({
name: row.querySelector('.name')?.textContent,
value: row.querySelector('.value')?.textContent,
}));
});
await page.screenshot({ path: '/mantle/artifacts/dashboard.png' });
console.log(JSON.stringify({ records: data, count: data.length }));
artifacts:
- path: dashboard.png
name: dashboard-screenshot
Example — TypeScript with form submission:
- name: submit-form
action: browser/run
timeout: "2m"
params:
language: typescript
output_format: json
script: |
const page = await browser.newPage();
await page.goto('https://portal.example.com/form');
await page.fill('#email', 'user@example.com');
await page.fill('#message', 'Automated submission');
await page.click('#submit-button');
await page.waitForSelector('.success-message');
const confirmationId = await page.textContent('.confirmation-id');
console.log(JSON.stringify({ submitted: true, confirmation_id: confirmationId }));
Example — Python with PDF generation:
- name: generate-pdf
action: browser/run
timeout: "2m"
params:
language: python
output_format: json
script: |
import os
import json
page.goto('https://example.com/report')
page.pdf(path='/mantle/artifacts/report.pdf')
file_size = os.path.getsize('/mantle/artifacts/report.pdf')
print(json.dumps({'generated': True, 'size_bytes': file_size}))
artifacts:
- path: report.pdf
name: generated-report
Playwright API Reference:
Within browser/run scripts, use the standard Playwright API:
- Page navigation:
page.goto(url),page.goBack(),page.goForward(),page.reload() - Interactions:
page.fill(selector, text),page.click(selector),page.selectOption(selector, value),page.press(key) - Waiting:
page.waitForSelector(selector),page.waitForNavigation(),page.waitForFunction(fn) - DOM queries:
page.textContent(selector),page.getAttribute(selector, name),page.evaluate(fn) - Screenshots/exports:
page.screenshot(options),page.pdf(options),page.recordHar(path)