HTTP, Files & Storage
Generic connectivity and I/O nodes: arbitrary HTTP/REST and gRPC calls, the universal connector node for third-party integrations, SFTP file transfer, per-tenant key-value storage, file/encoding utilities, and Cypher queries against Neo4j.
http
Makes an HTTP request to any URL and returns the parsed response. Supports JSON, form, multipart, text, XML, GraphQL, and binary request bodies.
{
"id": "fetch_user",
"type": "http",
"config": {
"method": "POST",
"url": "https://api.example.com/users",
"body_type": "json",
"body": { "email": "{{trigger.body.email}}" },
"headers": { "X-Api-Version": "2024-01-01" },
"auth_bearer": "{{secret.API_TOKEN}}",
"timeout_seconds": 30
}
}
| Field | Type | Default | Description |
|---|---|---|---|
method | string | "GET" | HTTP method, case-insensitive (normalized to uppercase). |
url | string | — | Required. Request URL. Supports {{ }} expressions. |
body_type | string | auto | Request body encoding — see table below. If unset, defaults to "none" for GET/DELETE/HEAD and "json" otherwise. |
body | any | — | Request body. Used by json, text, xml, graphql (fallback), and binary body types. |
form_fields | object | — | Field map for form and multipart body types. |
files | array | — | For multipart: list of { field_name, file_name, content_base64, content_type } objects to attach as file parts. |
graphql_query | string | — | GraphQL query string (used when body_type: "graphql"). Falls back to body if unset. |
graphql_variables | object | — | GraphQL variables object. |
query_params | object | — | Key/value pairs appended to the URL's query string (merged with any existing query string). |
headers | object | — | Request headers. Accepts a JSON object. Overrides the auto-set Content-Type. |
auth_username / auth_password | string | — | If auth_username is set, sends HTTP Basic auth. |
auth_bearer | string | — | If set (and resolves to a non-empty value), sends Authorization: Bearer <value>. |
content_type | string | "application/octet-stream" | Content-Type used for body_type: "binary". |
timeout_seconds | number | 60 | Per-request timeout override (the node's default HTTP client uses a 60s timeout). |
fail_on_error | string | "true" | If not "false", the step fails (returns an error) when the response status is >= 400. The parsed output is still returned alongside the error. |
body_type values
| Value | Content-Type sent | Body source |
|---|---|---|
none | — | No body (used for GET/DELETE/HEAD by default). |
json (default for non-GET) | application/json | body, JSON-encoded. If body is already a valid JSON string, it's sent as-is. |
form | application/x-www-form-urlencoded | form_fields (or body as a fallback object). |
multipart | multipart/form-data | form_fields for regular fields, files for file parts. |
text | text/plain; charset=utf-8 | body, stringified. |
xml | application/xml; charset=utf-8 | body, stringified. |
graphql | application/json | { "query": graphql_query (or body), "variables": graphql_variables }. |
binary | content_type (default application/octet-stream) | body, base64-decoded into raw bytes. |
Output:
| Field | Type | Description |
|---|---|---|
status / status_code | number | HTTP response status code. |
ok | boolean | true if status is in the 200-299 range. |
headers | object | Response headers, flattened to { "Header-Name": "comma, joined, values" }. |
body_raw | string | Raw response body as a string. |
body | any | Parsed response body — a JSON value if Content-Type contains application/json, a string if text/*, otherwise the raw text (binary responses also fall through here). |
body_base64 | string | Present only for non-text/non-JSON responses — the body base64-encoded. |
A response with status >= 400 returns this output and an error (unless fail_on_error: "false"), so continue_on: "error" steps can still inspect steps.<id>.output.status and body.
connector
Executes one action against a connector registered through the Connector SDK (connector-sdk/) — the plugin mechanism for custom/marketplace connectors that ship a manifest plus action handlers (sdk.NewFromManifest). These are managed via GET/POST /api/v1/connectors.
Note: The 66 built-in integrations (GitHub, Slack, Stripe, databases, ad platforms, etc. — see the Connector Reference) are a separate library (
internal/connectors) exposed only as AI agent tools via anagentnode'stoolsarray (see AI Agents — Connector tools), not through thisconnectornode.
{
"id": "post_message",
"type": "connector",
"config": {
"connector": "slack",
"action": "send_message",
"auth": {
"type": "api_key",
"fields": { "token": "{{secret.SLACK_TOKEN}}" }
},
"input": {
"channel": "#general",
"text": "Deployment finished: {{steps.deploy.output.version}}"
}
}
}
| Field | Type | Default | Description |
|---|---|---|---|
connector | string | — | Required. Connector identifier as registered in internal/connectors/registry.go (e.g. "slack", "tool-github"). |
action | string | — | Required. One of the actions the connector exposes. |
auth | object | — | { type, fields }. type is "none", "api_key", "oauth2", "basic", or "custom", matching the connector's auth schema. fields is a flat string map (e.g. { "token": "...", "access_token": "..." }), typically populated from {{secret.NAME}} or the tenant's stored connector credentials. |
input | object | — | Action-specific input parameters. If omitted, the step's resolved inputs map (upstream step outputs) is passed through as-is. |
Resolution path: the node looks up the connector by name in the global connector registry, builds an Auth{Type, Fields} from config.auth, builds the input map from config.input (or falls back to the step's inputs), and calls connector.Execute(ctx, action, auth, input).
Output: action-specific — the map returned by the connector's Execute implementation. See the Connector Reference for the full list of connectors, their actions, auth types, and per-action input/output shapes.
grpc-action
Calls any method on an external gRPC service using server-side reflection — no .proto files need to be bundled with the workflow.
{
"id": "say_hello",
"type": "grpc-action",
"config": {
"address": "api.example.com:443",
"method": "helloworld.Greeter/SayHello",
"payload": { "name": "{{trigger.body.name}}" },
"metadata": { "authorization": "Bearer {{secret.API_TOKEN}}" }
}
}
| Field | Type | Default | Description |
|---|---|---|---|
address | string | — | Required. host:port of the gRPC server. |
method | string | — | Required. package.ServiceName/MethodName (e.g. helloworld.Greeter/SayHello). The part before the last / is the fully-qualified service name; the part after is the method name. |
payload | object | {} | Request message fields, as JSON. Converted to the request proto via protojson after the schema is fetched through reflection. |
tls | string | "auto" | "true", "false", or "auto" — auto enables TLS when the address ends in :443. |
timeout_ms | number (string) | 30000 | Request timeout in milliseconds. |
metadata | object | {} | Outgoing gRPC metadata headers, e.g. { "authorization": "Bearer ..." }. |
How it works: the node dials the address, opens a gRPC server reflection (v1alpha) stream to fetch the FileDescriptorProto for the service, locates the method descriptor, builds a dynamic request message from payload via protojson.Unmarshal, invokes the method, and marshals the dynamic response message back to JSON. The target server must have gRPC reflection enabled.
Output:
| Field | Type | Description |
|---|---|---|
response | object | The decoded response message as a JSON object (with unpopulated fields emitted). |
method | string | The package.Service/MethodName that was called. |
address | string | The server address that was called. |
sftp
Performs file and directory operations against a remote server over SFTP/SSH.
{
"id": "upload_report",
"type": "sftp",
"config": {
"operation": "upload_file",
"host": "files.example.com",
"port": "22",
"username": "deploy",
"private_key": "{{secret.SFTP_PRIVATE_KEY}}",
"path": "/incoming/report.csv",
"content": "{{steps.build_csv.output.csv}}",
"encoding": "text"
}
}
Connection fields (all operations)
| Field | Type | Default | Description |
|---|---|---|---|
host | string | — | Required. Remote host. |
port | string | "22" | SSH port. |
username | string | — | SSH username. |
password | string | — | Password auth. Either password or private_key (or both) must be set. |
private_key | string | — | PEM-encoded private key for public-key auth (e.g. {{secret.SFTP_PRIVATE_KEY}}). |
operation | string | "list_files" | One of the operations below. |
Host key verification is not performed (InsecureIgnoreHostKey). Connection timeout is fixed at 30 seconds.
Operations
| Operation | Extra fields | Output |
|---|---|---|
list_files | path (default .) | files: array of { name, path, size, is_dir, modified, mode }; count. |
read_file | path | content (string), base64, size, path, name. |
upload_file | path, content, encoding ("text" or "base64", default "text") | path, bytes_written, name. Parent directories are created automatically. |
delete_file | path | path, deleted: true. |
rename | from, to | from, to, renamed: true. |
create_folder | path | path, created: true. Creates intermediate directories as needed. |
delete_folder | path | path, deleted: true. Directory must be empty. |
store
Durable per-tenant key-value storage backed by the workflow_kv_store table (see Multi-Tenancy). Reads always go to the database, so values are correct across Temporal workflow replays.
{
"id": "remember_count",
"type": "store",
"config": {
"operation": "put",
"scope": "execution",
"key": "processed_count",
"value": "{{steps.count_items.output.count}}"
}
}
| Field | Type | Default | Description |
|---|---|---|---|
operation | string | "get" | One of the operations below. |
scope | string | "execution" | "execution" — isolated to the current workflow run (keyed by execution_id); "global" — shared across all runs for the tenant. |
key | string | — | The KV key. Supports {{ }} expressions. |
value | any | — | Value to write (put, append, add_to_list, remove_from_list). |
default_value | any | — | Returned by get when the key doesn't exist. |
separator | string | "" | Separator inserted between existing and new value for append. |
item | any | — | Item to add/remove for add_to_list / remove_from_list. |
Operations
| Operation | Description | Output |
|---|---|---|
get | Read a key. Returns default_value if not found. | value, found (boolean). |
put | Upsert a key's value (JSON-encoded). | key, value, operation: "put". |
delete | Remove a key. | key, deleted: true. |
append | String-concatenate value onto the existing string value, joined by separator. | value (the new string), key. |
add_to_list | Append item to a JSON array stored at key (creates it if absent). | list, count, key. |
remove_from_list | Remove all elements equal to item (compared as strings) from the array. | list, count, key. |
list_keys | List all keys for the current tenant + scope. | keys (array of strings), count, scope. |
clear | Delete all keys for the current tenant + scope. | cleared: true, scope. |
file-helper
Encoding, decoding, and metadata utilities for in-workflow file content (base64 strings, MIME types, filenames). Operates purely on values passed through config/inputs — it does not touch the sandbox filesystem.
{
"id": "encode_attachment",
"type": "file-helper",
"config": {
"operation": "to_base64",
"content": "{{steps.fetch_doc.output.body}}"
}
}
| Field | Type | Default | Description |
|---|---|---|---|
operation | string | "to_base64" | One of the operations below. |
content | string | — | Source content (text or already-encoded), depending on operation. |
name | string | — | Filename, used for extension/MIME detection. |
path | string | — | Path string for get_name. |
encoding | string | "text" | For create: "text" or "base64" — whether content is already base64. |
from_encoding / to_encoding | string | "utf8" / "base64" | For change_encoding: source/target encodings ("utf8" or "base64"). |
base64 | string | — | Input for from_base64. |
Operations
| Operation | Output |
|---|---|
to_base64 | base64, size (bytes of content), encoding: "base64". |
from_base64 | content (decoded string, tries standard/raw/URL base64), size. |
create | name, content, base64, mime_type, extension, size. Builds a "virtual file" object from content + name. |
get_name | name, extension, dir, stem — derived from path. |
check_type | mime_type, extension, is_text, is_image, is_pdf, is_binary. MIME is detected from name's extension, falling back to content-sniffing (PDF/JPEG/PNG/GIF/WebP magic bytes). |
get_extension | extension, name, mime_type — derived from name. |
change_encoding | result (re-encoded content), size. |
neo4j
Runs a Cypher query against a Neo4j graph database. Works for both reads (MATCH ... RETURN) and writes (CREATE / MERGE / SET) — Neo4j's auto-commit transaction picks the access mode based on the query.
{
"id": "find_related",
"type": "neo4j",
"config": {
"uri": "neo4j+s://my-instance.databases.neo4j.io",
"username": "neo4j",
"password": "{{secret.NEO4J_PASSWORD}}",
"database": "neo4j",
"query": "MATCH (n:Person)-[:KNOWS]->(m) WHERE n.name = $name RETURN m.name AS name",
"params": { "name": "{{trigger.body.name}}" },
"timeout_ms": 15000
}
}
| Field | Type | Default | Description |
|---|---|---|---|
uri | string | — | Required. e.g. neo4j://localhost:7687 or neo4j+s://<host>. |
username | string | "neo4j" | Database username. |
password | string | "" | Database password. Supports {{ }} expressions, e.g. {{secret.NEO4J_PASSWORD}}. |
query | string | — | Required. Cypher query. Supports {{ }} expressions. |
database | string | server default | Optional database name (Neo4j multi-database). |
params | object | {} | Cypher $parameters, as a JSON object. Each value is independently resolved for {{ }} expressions. |
timeout_ms | number | 15000 | Query timeout in milliseconds. |
Output:
| Field | Type | Description |
|---|---|---|
records | array of objects | Each record from the result, converted via record.AsMap() (column name -> value). |
keys | array of strings | The result's column names. |
count | number | Number of records returned. |
counters | object | Write statistics: nodes_created, nodes_deleted, relationships_created, relationships_deleted, properties_set, labels_added. |