XY Logo
Developer hub

Custom workflows

Describe the work. Test the reality. Promote deliberately.

Planner turns a natural-language operating specification into tested activities and a reusable workflow. It is a durable review loop—not a single prompt that silently deploys code.

Mental model

The production boundary is explicit.

A build is authoring state. A step is a proposed activity. Promotion creates a reusable workflow definition. A schedule operates that definition. A run is one execution.
1

Build

Describe a new flow or supply existing YAML to modify.

2

Test

Planner runs real partial workflow tests and repairs failures.

3

Decide

Accept, reject, retry, message, or test an edit for every step.

4

Promote

Create a pinned organization production definition.

5

Operate

Schedule, trigger, observe phases, and query analytics.

Capability boundary

What you can build through the API today.

Production workflows demonstrate that the orchestration model can support much more than a linear browser macro. The table below says which of those building blocks are actually partner-accessible today.
CapabilityAvailabilityWhat that means
Portal navigation, extraction, upload, and downloadSelf-servicePlanner creates a browser step; use Studio when it needs direct work.
Pure computation and data normalizationSelf-servicePlanner can create organization-scoped compute activities.
OCR and structured document extractionSelf-servicePlanner can compose the platform OCR activity and downstream transforms.
Sequence, parallel work, loops, branches, child flows, and error handlingSelf-serviceDescribe cardinality, concurrency, stop rules, and failure behavior explicitly.
Call an existing integration capabilityExisting setup requiredThe organization must already have an active connection and exposed capability.
Create a new arbitrary integration or connectorXY-builtIntegration Factory creation is not currently a partner API operation.
Password, TOTP, PIN, and portal credential useSelf-serviceCreate a vault reference and bind its ID; secrets never belong in the Planner request.
Automated SMS or email OTP retrievalExisting setup requiredA phone field alone does not provision an inbox, carrier, or messaging integration.
Specialized queues, entity writeback, webhooks, or typed domain clientsXY-builtSubmit the interfaces and acceptance criteria as a custom-agent request.
Recurring production executionSelf-servicePromote, then create and operate a workflow schedule.
One-off execution of any promoted Planner definitionNot exposedOnly an existing schedule can be triggered immediately; published agents have their own execution route.
Run phases and governed analyticsSelf-service read-onlyRead phase projections and approved metrics without changing runtime state.
Build reporting in a partner UISelf-service read-onlyUse aggregate metrics or presentation-ready metric views with tile data and visualization metadata.
Create or edit XY dashboard definitionsNot exposedThe partner API returns analytics data but does not author dashboard configurations inside XY.
Start Browser StudioExisting Planner step requiredStudio creates a separate retained authoring Chrome for an existing run_browser_workflow step.

Start and follow

Treat Planner like a durable state machine.

Build creation is asynchronous and idempotent. The request describes outcomes and constraints; context supplies public URLs, safe input/output descriptions, and credential references—not secrets.
1. Queue the build
curl --fail-with-body --request POST \
  --header "Authorization: Bearer ${XY_API_KEY}" \
  --header "Idempotency-Key: portal-reconciliation-v1" \
  --header "Content-Type: application/json" \
  "${XY_API_BASE}/planner/builds" \
  --data '{
    "request": "Sign in, collect open records, normalize them, and return a per-record result.",
    "context": {
      "portal_url": "https://portal.example.com/open-records",
      "credential_id": "cred_REPLACE",
      "inputs": [{"name": "cutoff_date", "type": "string"}],
      "outputs": [{"name": "results", "type": "array"}]
    }
  }'
2. Replay and tail events
# Replay durable events, then keep following new ones.
curl --fail-with-body --no-buffer \
  --header "Authorization: Bearer ${XY_API_KEY}" \
  --header "Accept: text/event-stream" \
  "${XY_API_BASE}/planner/builds/${BUILD_ID}/events?after=0&stream=true"

# Reconnect without restarting Planner work.
curl --fail-with-body \
  --header "Authorization: Bearer ${XY_API_KEY}" \
  "${XY_API_BASE}/planner/builds/${BUILD_ID}/events?after=${LAST_EVENT_ID}"

Write a request that can be tested

  • Name the source, destination, and trigger.
  • Define input and output shapes, including empty cases.
  • State which confirmation proves a write succeeded.
  • Describe list cardinality and concurrency limits.
  • Say what retries, skips, and partial failures mean.
  • Identify human gates such as login, MFA, or review.
  • Separate required results from diagnostic metadata.
  • Use a credential ID; never embed a secret.

Review

Every step waits for your decision.

A passing mechanical test is evidence, not approval. Review item counts, output shape, business conditions, and downstream mappings before accepting.
Accept the tested step
curl --fail-with-body --request POST \
  --header "Authorization: Bearer ${XY_API_KEY}" \
  --header "Idempotency-Key: ${BUILD_ID}-step-1-accept-v1" \
  --header "Content-Type: application/json" \
  "${XY_API_BASE}/planner/builds/${BUILD_ID}/steps/1/actions" \
  --data "{
    "action": "ACCEPT",
    "expected_state_version": ${STATE_VERSION}
  }"

Available actions

ACCEPT
Record approval and advance. Edits are tested first.
REJECT
Give concrete feedback and regenerate the step.
MESSAGE
Continue the Planner conversation with context.
RETRY
Reset and regenerate the current step.
TEST
Run supplied code or full step YAML without accepting it.

Promote and operate

Authoring ends before production begins.

Promotion requires its own privileged scope and never happens automatically. Generated database activities are pinned to the accepted version in the production definition.
Promote the completed build
curl --fail-with-body --request POST \
  --header "Authorization: Bearer ${XY_API_KEY}" \
  --header "Idempotency-Key: ${BUILD_ID}-promote-v1" \
  --header "If-Match: ${STATE_VERSION}" \
  --header "Content-Type: application/json" \
  "${XY_API_BASE}/planner/builds/${BUILD_ID}/promote" \
  --data '{
    "name": "Portal record reconciliation",
    "description": "Collects and normalizes open records."
  }'
Create and trigger a schedule
curl --fail-with-body --request POST \
  --header "Authorization: Bearer ${XY_API_KEY}" \
  --header "Content-Type: application/json" \
  "${XY_API_BASE}/workflow-definitions/${WORKFLOW_DEFINITION_ID}/schedule" \
  --data '{
    "cron_expression": "0 9 * * 1-5",
    "input": {"region": "west"},
    "overlap_policy": "SKIP",
    "note": "Weekday run"
  }'

# Trigger that existing schedule now.
curl --fail-with-body --request POST \
  --header "Authorization: Bearer ${XY_API_KEY}" \
  --header "Content-Type: application/json" \
  "${XY_API_BASE}/workflow-definitions/${WORKFLOW_DEFINITION_ID}/schedule/trigger" \
  --data '{}'

Schedule safely

Choose an overlap policy, freeze explicit input, and update the schedule when its input contract changes.

Observe phases

Read execution or workflow-run phases without mutating the underlying run.

Query analytics

Read aggregate metrics or presentation-ready tile data, then render the charts and dashboards in your own product.