Push local .workflow.yaml files to the Agents Platform, creating new workflows or updating existing ones using idempotent operations.
# Push a workflow file
workflow push my-workflow.workflow.yaml
# First push creates, subsequent pushes update
workflow push my-workflow.workflow.yaml # Creates workflow
workflow push my-workflow.workflow.yaml # Updates same workflow (idempotent)| Option | Short | Description |
|---|---|---|
FILE |
Path to .workflow.yaml file to push |
The push command follows a multi-stage workflow:
- Load & Validate — Loads YAML and runs all validation checks (same as
workflow validate) - Check Lockfile — Reads
.workflow.lockto determine create vs. update mode - Resolve Dependencies — Converts human-friendly names to UUIDs using a 3-tier strategy:
- UUID passthrough — if the value is already a UUID, use it as-is (no API call)
- Lockfile cache — if a previous push cached the mapping, reuse it (no API call)
- API lookup — query the platform for
agent_name→agentId,knowledge_base_name→knowledgeBaseId
- Convert to API Payload — Transforms WDF format to platform API format
- Generate Layout — Auto-generates node positions for visual editor
- Push to Platform — Calls atomic save endpoint (single transaction)
- Write Lockfile — Saves
.workflow.lockwith server-assigned UUIDs
The lockfile enables idempotent push operations by tracking:
- workflow_id — Server-assigned workflow UUID
- organization_id — Organization UUID
- nodes — Mapping of node slug → server-assigned node UUID
- edges — Mapping of edge "source→target" → server-assigned edge ID
- dependencies — Cached name-to-UUID mappings for agents and knowledge bases (keys use
agent:{name}orkb:{name}format) - pushed_at — Timestamp of last successful push
- instance — Platform instance URL
Example lockfile:
# Auto-generated by workflow CLI. Do not edit manually.
version: 1
workflow_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
organization_id: 11111111-2222-3333-4444-555555555555
instance: https://api.sb.allogy.com
pushed_at: '2025-02-18T10:30:45.123456Z'
nodes:
input: 22222222-3333-4444-5555-666666666666
llm: 33333333-4444-5555-6666-777777777777
output: 44444444-5555-6666-7777-888888888888
edges:
input->llm: 10001
llm->output: 10002
dependencies:
agent:Customer Support Agent: 8cc8beec-11b2-4d35-a88b-424727111d6a
kb:Company Policies: 6c26048d-2f9c-4177-a126-f2ed8cd02a0eLockfile behavior:
- Lockfile is automatically created on first push
- Lockfile is automatically updated on subsequent pushes
- Lockfile should be committed to version control for team collaboration
- Lockfile enables idempotent updates (same command creates or updates)
The push command resolves human-friendly names (agent_name, knowledge_base_name, knowledge_base_names) to platform UUIDs using a 3-tier strategy (checked in order):
- UUID passthrough — If the value is already a valid UUID (e.g.,
e0b3bdc6-9fcb-45ee-8833-26aa5cd1d2e0), it is used directly. No API call is made. - Lockfile cache — If a previous push already resolved this name and cached the UUID in the
.workflow.lockfile'sdependenciessection, the cached value is reused. No API call is made. - API lookup — The platform API is queried to find the resource by name (case-insensitive). On failure, the error lists all available resources of that type in the organization.
Resolved mappings are automatically cached in the lockfile after each successful push, so subsequent pushes avoid redundant API calls.
When your workflow uses agent nodes, you can reference agents by name:
Before resolution (in .workflow.yaml):
nodes:
my_agent:
type: agent
execution_mode: MESSAGES
label: My Agent
config:
agent_name: Customer Support Agent # Human-friendly name
primaryInput: "{{input.output.text}}"After resolution (in API payload):
{
"config": {
"agentId": "a1b2c3d4-...", // Resolved UUID
"primaryInput": "{{<uuid>.output.text}}"
}
}When your workflow uses retrieval nodes, you can reference knowledge bases by name:
Before resolution (in .workflow.yaml):
nodes:
retrieval:
type: retrieve
execution_mode: FLOW
label: Document Search
config:
knowledge_base_name: Company Policies # Human-friendly name
topK: 5
scoreThreshold: 0.7After resolution (in API payload):
{
"config": {
"knowledgeBaseId": "b2c3d4e5-...", // Resolved UUID
"topK": 5,
"scoreThreshold": 0.7
}
}If you already have a platform UUID (e.g., from a lockfile or the platform UI), you can use it directly in place of a name. The push command detects UUID strings and passes them through without making any API call:
nodes:
my_agent:
type: agent
execution_mode: MESSAGES
label: My Agent
config:
agent_name: e0b3bdc6-9fcb-45ee-8833-26aa5cd1d2e0 # UUID used as-isThis is useful for pinning a workflow to a specific resource or working in environments where name-based lookup is not desired.
RAG agent nodes (rag_agent) can reference multiple knowledge bases using the knowledge_base_names list:
nodes:
rag:
type: rag_agent
execution_mode: MESSAGES
label: RAG Agent
config:
agent_name: Data Analyst Agent
knowledge_base_names: # List of KB references
- Company Policies
- Industry StandardsEach entry in the list is resolved independently using the same 3-tier strategy. You can also mix names and UUIDs within the list.
Variable references use the format {{slug.output.field}} to access outputs from upstream nodes. The .output. delimiter and a specific field path are required — using just {{slug.output}} without a field will fail at runtime.
Structured input data is stored with each form field accessible at {{slug.output.field_name}}:
nodes:
form:
type: structured_input
execution_mode: INPUT
config:
schema:
type: object
properties:
name: { type: string }
topic: { type: string }
process:
type: llm_call
execution_mode: MESSAGES
config:
model: us.anthropic.claude-sonnet-4-20250514-v1:0
# Correct: reference specific fields
template: "Name: {{form.output.name}}\nTopic: {{form.output.topic}}"
# WRONG: {{form.output}} — will fail with "Invalid reference format"Retrieve node results are accessible at {{slug.output.results}} (array of documents):
nodes:
search:
type: retrieve
execution_mode: FLOW
config:
knowledge_base_name: my_kb
topK: 5
searchQuery: "{{form.output.topic}}"
summarize:
type: llm_call
execution_mode: MESSAGES
config:
model: us.anthropic.claude-sonnet-4-20250514-v1:0
# Correct: reference the results array
template: "Context: {{search.output.results}}\n\nSummarize the above."
# WRONG: {{search.output}} — will fail with "Invalid reference format"| Node Type | Primary Output Path | Description |
|---|---|---|
structured_input |
{{slug.output.field_name}} |
Individual form fields |
plain_txt_input |
{{slug.output.text}} |
Text content |
llm_call |
{{slug.output.text}} |
Generated text |
agent |
{{slug.output.response}} |
Agent response text |
retrieve |
{{slug.output.results}} |
Retrieved documents array |
structured_output |
{{slug.output.structured}} |
Structured JSON output |
file_upload |
{{slug.output.text}} |
Extracted text from files |
If an agent or knowledge base cannot be found, the push fails with a helpful error listing available alternatives:
Cannot resolve agent 'Customer Support Agent'. Available agents: Data Analyst Agent, Code Assistant Agent, OpenAI Test Agent
Cannot resolve knowledge base 'Company Policies'. Available knowledge bases: standards, industry, whitelisted
If no resources of that type exist in the organization:
Cannot resolve agent 'My Agent'. No agents available in this organization.
The push command auto-generates node positions for the visual workflow editor using a simple vertical layout algorithm:
- Entry nodes at top (y=100)
- Subsequent nodes spaced vertically (y += 150)
- All nodes horizontally centered (x=200)
This ensures workflows are immediately viewable in the platform's visual editor without manual positioning.
The push command automatically detects whether to create or update based on lockfile presence:
# First push - no lockfile exists
workflow push customer-support.workflow.yaml
# Output:
# ✓ Loaded workflow: Customer Support Workflow
# ✓ Validation passed (all checks passed)
# ✓ Resolved dependencies: 1 agent, 0 knowledge bases
# ✓ Pushed workflow (created)
# ✓ Lockfile saved: customer-support.workflow.lock# Subsequent push - lockfile exists
workflow push customer-support.workflow.yaml
# Output:
# ✓ Loaded workflow: Customer Support Workflow
# ✓ Validation passed (all checks passed)
# ✓ Resolved dependencies: 1 agent, 0 knowledge bases
# ✓ Pushed workflow (updated: a1b2c3d4-...)
# ✓ Lockfile updated: customer-support.workflow.lockThe push command requires CLI configuration (same as other commands):
Environment variables:
export WORKFLOW_API_HOST=https://api.sb.allogy.com
export WORKFLOW_API_KEY=your-api-key
export WORKFLOW_ORG_ID=your-org-uuid
# Optional: send a user JWT as a Bearer token for endpoints that reject
# API-key auth (e.g. workflow creation on some environments).
export WORKFLOW_JWT=your-jwt-access-tokenOr config file (~/.workflow/config.yaml):
host: https://api.sb.allogy.com
api_key: your-api-key
org_id: your-org-uuidOr CLI flags:
workflow push my-workflow.workflow.yaml \
--host https://api.sb.allogy.com \
--api-key your-api-key \
--org your-org-uuidSee README.md for full configuration details.
# Create workflow file
workflow init --template text-to-agent -o simple.workflow.yaml
# Push to platform
workflow push simple.workflow.yaml
# Output:
# ✓ Loaded workflow: Text to Agent
# ✓ Validation passed
# ✓ Pushed workflow (created)
# ✓ Lockfile saved: simple.workflow.lock# customer-support.workflow.yaml
name: Customer Support
nodes:
input:
type: plain_txt_input
execution_mode: INPUT
config:
placeholder: Enter customer question
agent:
type: agent
execution_mode: MESSAGES
config:
agent_name: Customer Support Agent # Resolved automatically
primaryInput: "{{input.output.text}}"
edges:
- from: input
to: agent
entry: input
exit: agent# Push resolves agent_name to UUID automatically
workflow push customer-support.workflow.yaml
# Output:
# ✓ Loaded workflow: Customer Support
# ✓ Validation passed
# ✓ Resolved dependencies: 1 agent
# ✓ Pushed workflow (created)# document-qa.workflow.yaml
name: Document Q&A
nodes:
input:
type: plain_txt_input
execution_mode: INPUT
config:
placeholder: Ask a question
retrieval:
type: retrieve
execution_mode: FLOW
config:
knowledge_base_name: Company Policies # Resolved automatically
topK: 5
llm:
type: llm_call
execution_mode: MESSAGES
config:
model: anthropic.claude-3-5-sonnet-20241022-v2:0
template: "Context: {{retrieval.output.text}}\n\nQuestion: {{input.output.text}}"
edges:
- from: input
to: retrieval
- from: retrieval
to: llm
entry: input
exit: llm# Push resolves knowledge_base_name to UUID automatically
workflow push document-qa.workflow.yaml
# Output:
# ✓ Loaded workflow: Document Q&A
# ✓ Validation passed
# ✓ Resolved dependencies: 0 agents, 1 knowledge base
# ✓ Pushed workflow (created)# Edit workflow file
vim customer-support.workflow.yaml
# Push updates (lockfile determines update mode)
workflow push customer-support.workflow.yaml
# Output:
# ✓ Loaded workflow: Customer Support (updated)
# ✓ Validation passed
# ✓ Resolved dependencies: 1 agent
# ✓ Pushed workflow (updated: a1b2c3d4-...)
# ✓ Lockfile updatedPush command runs full validation before any API calls:
workflow push broken-workflow.workflow.yaml
# Output:
# ✗ Validation failed: Cycle detected: a -> b -> a
# Push aborted (fix validation errors first)Fix: Run workflow validate to see all validation errors, then fix them.
workflow push customer-support.workflow.yaml
# Output:
# ✓ Loaded workflow: Customer Support
# ✓ Validation passed
# ✗ Cannot resolve agent 'Customer Support Agent'. Available agents: Data Analyst Agent, Code Assistant Agent
# Push abortedFix: Ensure the agent or knowledge base name matches an existing resource in your organization. Use workflow push to see the list of available alternatives in the error message. You can also use a UUID directly instead of a name to bypass the lookup.
workflow push my-workflow.workflow.yaml
# Output:
# ✓ Loaded workflow: My Workflow
# ✓ Validation passed
# ✓ Resolved dependencies
# ✗ API Error: 403 Forbidden - Insufficient permissionsFix: Check your API key permissions, ensure you have write access to workflows in your organization.
workflow push my-workflow.workflow.yaml
# Output:
# ✓ Loaded workflow: My Workflow
# ✓ Validation passed
# ✗ Network Error: Connection timeout
# Push aborted (workflow not created)Fix: Check your network connection and platform instance URL.
# 1. Scaffold from template
workflow init --template rag-qa -o qa.workflow.yaml
# 2. Validate before push
workflow validate qa.workflow.yaml
# 3. Push to platform
workflow push qa.workflow.yaml
# 4. Update and re-push
vim qa.workflow.yaml
workflow validate qa.workflow.yaml
workflow push qa.workflow.yaml#!/bin/bash
# .github/workflows/deploy-workflows.sh
set -e
# Validate all workflows
for workflow in workflows/*.workflow.yaml; do
echo "Validating $workflow..."
uv run workflow validate "$workflow"
done
# Push all workflows
for workflow in workflows/*.workflow.yaml; do
echo "Pushing $workflow..."
uv run workflow push "$workflow"
done
echo "All workflows deployed successfully!"- Always validate before pushing — Catch errors early with
workflow validate - Commit lockfiles to version control — Track workflow UUIDs alongside code
- Use descriptive names for dependencies — Makes workflows more readable
- Test in dev environment first — Use separate API keys for dev/staging/prod
- Review lockfile after first push — Verify workflow_id matches expected org
If lockfile references a workflow that was deleted on the platform:
# Delete lockfile to force create mode
rm my-workflow.workflow.lock
# Push creates new workflow
workflow push my-workflow.workflow.yamlWhen working with multiple organizations, use CLI flags or separate config files:
# Push to org A
workflow push --org org-a-uuid my-workflow.workflow.yaml
# Push to org B
workflow push --org org-b-uuid my-workflow.workflow.yaml- Jira Ticket: RAG-951 (Push Command), RAG-949 (Lockfile Management), RAG-950 (Dependency Resolution)
- Related Commands:
workflow validate,workflow init - Lockfile Format: See
src/cli/lockfile.pyfor schema - API Endpoint:
POST /api/v1/workflows/complete(atomic save) - WDF Schema: See
docs/validate-command.mdfor node types