---
orphan: true
---

# Build a workflow with natural language through the API

Send data sources, processing requirements, and output destinations to the workflow assistant. Review its candidate, accept it, then deploy and run it. Generation, acceptance, deployment, and execution are separate steps.

## Prepare the environment and workflow assistant

Prepare a [personal access token](../../../../../guides/genesis/api-keys.md) with access to the target workspace and permission to create workflows, and the [workspace ID](../../../../../guides/ai-studio/resource-center/workspace.md#copy-a-workspace-id). Examples use `$AI_STUDIO_API_KEY` and `$WORKSPACE_ID`.

1. [Query the agent list](../../agents/agents/list-agents.md) and find an active system workflow assistant. Do not restrict discovery to a display scene intended only for ordinary chat.
2. Save `id` and `workspace_id` from the same item as `$AGENT_ID` and `$AGENT_WORKSPACE_ID`. The agent may belong to a different workspace from the task.
3. [Get the Agent Card](../../agents/agent-invocation/get-agent-card.md) using the target workspace and agent ID in the path and the agent's owning workspace in the query. Check text input and A2A capabilities.
4. [List available models](../../agents/model-configurations/list-available-models.md) and use a returned `model` as `$MODEL`. Workflow generation requires `params.model`. This generation model is separate from models selected for AI nodes at runtime. The saved model configuration list is not the available model list; an empty configuration list does not establish that no models are available.

The workspace-scoped paths below use the task's `$WORKSPACE_ID`, matching the request header. `$AGENT_WORKSPACE_ID` in the query identifies the agent's owning workspace. For a system assistant, use `system` in the query and the actual target workspace in the path.

If the Card's `url` contains an internal deployment address, use the public workspace-scoped path below and do not send credentials to the internal address. Generic `/v5/agents/card` and `/v5/agents/a2a` are separate endpoints; their errors do not replace diagnosis through the workspace-scoped endpoints.

## Submit natural-language requirements

Send an A2A `message/send` request. Generate a unique `$MESSAGE_ID`; `conversation_purpose` marks the conversation for workflow generation. An existing conversation is not required for the first message. For revisions in the same conversation, set `params.message.contextId` to the previous task's `result.contextId`, generate a new `messageId`, and supply `params.model` again.

```bash
curl -X POST "https://api.moi.matrixorigin.cn/v5/workspaces/$WORKSPACE_ID/agents/$AGENT_ID/a2a?agent_workspace_id=$AGENT_WORKSPACE_ID" \
  -H "X-API-Key: $AI_STUDIO_API_KEY" \
  -H "X-Workspace-ID: $WORKSPACE_ID" \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": "generate-workflow-1",
    "method": "message/send",
    "params": {
      "model": "'"$MODEL"'",
      "metadata": {
        "conversation_purpose": "workflow"
      },
      "message": {
        "kind": "message",
        "role": "user",
        "messageId": "'"$MESSAGE_ID"'",
        "parts": [
          {
            "kind": "text",
            "text": "Create a manually triggered text-cleaning workflow with a required string input text. Use a registered text-cleaning operator and enable HTML tag removal by default. Submit a deployable candidate and runtime form; do not deploy or run it."
          }
        ]
      }
    }
  }'
```

Replace the example text with your requirements, including input types, all processing steps, output format, target resources, and failure handling. This text-cleaning example needs no external business data or storage destination. Add a save step and target resource if you need a file artifact. Configure credentials through supported platform mechanisms, not in the prompt.

## Track generation and inspect the candidate

When the response contains an A2A task, save `result.id` as `$TASK_ID`. Query it using the same agent selectors:

```bash
curl -X POST "https://api.moi.matrixorigin.cn/v5/workspaces/$WORKSPACE_ID/agents/$AGENT_ID/a2a?agent_workspace_id=$AGENT_WORKSPACE_ID" \
  -H "X-API-Key: $AI_STUDIO_API_KEY" \
  -H "X-Workspace-ID: $WORKSPACE_ID" \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": "get-workflow-candidate-1",
    "method": "tasks/get",
    "params": {
      "id": "'"$TASK_ID"'"
    }
  }'
```

`submitted` and `working` are not terminal. For `input-required` or `auth-required`, provide the requested information or authorization. Stop deployment for `failed`, `canceled`, or `rejected`. See [Call an agent from another agent](../../agents/agent-invocation/call-agent-from-agent.md) for details.

After `completed`, check `result.artifacts` for a deployable `workflow.candidate`. Its `metadata.matrixflow_type` identifies the artifact type; a `kind=data` part in `parts` carries the candidate in `data`. Save that artifact's `artifactId` as `$ARTIFACT_ID`. Do not substitute a conversation, message, or JSON-RPC request ID.

Inspect `ok`, `workflow`, `runtime_fields`, `runtime_layout`, and `diagnostics`:

- Nodes and input bindings cover all requirements, and referenced operators, models, and resources are available.
- Required form fields, types, and output destinations are correct.
- The candidate is valid and has no deployment-blocking diagnostics.

Text explanations, tool logs, and completed tasks without a valid candidate cannot be deployed. Request revisions in natural language, then accept the new candidate reference. Do not edit candidate content and reuse its original reference.

## Accept and deploy the candidate

1. [Accept the workflow candidate](accept-workflow-candidate.md) using `$TASK_ID` and `$ARTIFACT_ID`. Acceptance saves a confirmation record and does not start the workflow.
2. Prepare `default_values` from `runtime_fields.fields`, providing actual values for every required field. [Create the workflow](create-workflow.md#natural-language-candidate-deployment) with `source_type=nl2dsl`, the accepted `candidate_ref`, `execution_mode=one_shot`, and these defaults. Missing required values prevent deployment. Do not submit `dsl_yaml`, `runtime_fields`, `runtime_layout`, or `design_graph`; the server obtains the definition and form from the accepted candidate.
3. Save `data.workflow.id` and the deployment version. [Read workflow details](get-workflow.md) to verify the saved definition.

## Run and verify results

[Start a workflow job](../workflow-jobs/start-workflow-job.md) using the workflow ID, actual form-compatible `values`, and `trigger_now=true` when immediate execution is needed. Do not send `run_once`; the deployed `execution_mode=one_shot` already determines single-run behavior.

Save `data.workflow_run.execution_id`, then read [job details](../workflow-jobs/get-workflow-job.md) and [job results](../workflow-jobs/get-workflow-job-result.md) to verify the terminal state and artifacts. Deployment success or a queued job is not processing success. For file outputs, also verify that the file was saved and can be downloaded.

## Troubleshooting

- `workflow agent model is required`: provide `params.model` from the available model list, not a model configuration ID.
- A completed task has no `workflow.candidate`: save the task and tool results, then ask the assistant to continue or revise in the same conversation. Do not deploy based only on `completed`.
- HTTP 500 with generic `ErrServer`: save the request time, request/trace IDs, and JSON-RPC ID. Check the workspace-scoped endpoint described in [Call an agent from another agent](../../agents/agent-invocation/call-agent-from-agent.md); do not infer a model, permission, or missing-agent problem from a generic error.
- A request ends without a definitive response: [list runtime tasks](../../agents/runtime-observability/list-runtime-tasks.md) and match agent, context, and input summary, or [query sessions](../../agents/agent-sessions/list-sessions.md) to recover the active task. Query the actual task ID before resubmitting. A JSON-RPC, message, or conversation ID is not a task ID.
