{
  "schemaVersion": "1.0",
  "title": "Dify workflows, streaming, and human input",
  "description": "Use this family to inspect workflow runs and logs, execute a published workflow version, stop active generation, resume workflow events, and answer a paused human-input form. The nine operations use one configured Dify app credential.",
  "canonical": "https://getaip.org/docs/connectors/dify/capabilities/workflows-streaming-and-human-input",
  "route": "/docs/connectors/dify/capabilities/workflows-streaming-and-human-input",
  "source": "docs/connectors/dify/capabilities/workflows-streaming-and-human-input.md",
  "protocol": "Agent Interoperability Protocol",
  "protocolVersion": "1.0",
  "section": "Connectors",
  "documentType": "Connector",
  "language": "en",
  "downloads": {
    "md": "/docs/download/connectors/dify/capabilities/workflows-streaming-and-human-input.md",
    "txt": "/docs/download/connectors/dify/capabilities/workflows-streaming-and-human-input.txt",
    "json": "/docs/download/connectors/dify/capabilities/workflows-streaming-and-human-input.json",
    "pdf": "/docs/download/connectors/dify/capabilities/workflows-streaming-and-human-input.pdf"
  },
  "content": {
    "format": "text/markdown",
    "markdown": "---\ntitle: Dify workflows, streaming, and human input\ndescription: >-\n  Inspect and control Dify workflow tasks, resume bounded event streams, and\n  complete one-shot human-input forms through the frozen connector\nkind: capability-reference\naudience: application-developer\nappliesTo: \"1.x\"\nwritingStandard: \"aip-docs/1.0\"\nlastReviewedRevision: \"97be86e9efedf07ecf1783b03800f683f107fb04\"\nconnector: dify\n---\n\n# Dify workflows, streaming, and human input\n\nUse this family to inspect workflow runs and logs, execute a published workflow\nversion, stop active generation, resume workflow events, and answer a paused\nhuman-input form. The nine operations use one configured Dify app credential.\n\nTask control is not proof of terminal provider state. Preserve the app, end\nuser, task, workflow run, and form identities until a read or terminal event\nestablishes the outcome.\n\n## Choose an operation\n\n| Operation suffix | Method and route | Connector modes | Result | Policy |\n|---|---|---|---|---|\n| `completion.stop` | `POST /v1/completion-messages/{task_id}/stop` | `completion` | JSON | Medium mutation; approval and key required |\n| `chat.stop` | `POST /v1/chat-messages/{task_id}/stop` | Four chat-like modes | JSON | Medium mutation; approval and key required |\n| `workflow.run.get` | `GET /v1/workflows/run/{workflow_run_id}` | `workflow`, `advanced-chat` | JSON | Low-risk read; retry supported |\n| `workflow.run_by_id` | `POST /v1/workflows/{workflow_id}/run` | `workflow` | SSE or blocking JSON | High mutation; approval and key required |\n| `workflow.stop` | `POST /v1/workflows/tasks/{task_id}/stop` | `workflow` | JSON | Medium mutation; approval and key required |\n| `workflow.log.list` | `GET /v1/workflows/logs` | `workflow`, `advanced-chat` | JSON | Low-risk read; retry supported |\n| `workflow.event.stream` | `GET /v1/workflow/{task_id}/events` | `workflow` | SSE | Low-risk read; retry supported |\n| `human_input_form.get` | `GET /v1/form/human_input/{form_token}` | All six app modes | JSON | Low-risk read; retry supported |\n| `human_input_form.submit` | `POST /v1/form/human_input/{form_token}` | All six app modes | JSON | Medium mutation; approval and key required |\n\nThe four chat-like modes are `chat`, `advanced-chat`, `agent-chat`, and\n`agent`. Connector discovery exposes `workflow.event.stream` only for\n`workflow`, although the pinned provider route also accepts `advanced-chat`.\n\nThe capability template is:\n\n```text\ncap:dify:<app_id>:<operation>\n```\n\nUse tenant discovery to obtain the exact capability ID. A task ID, workflow\nrun ID, workflow version ID, or form token does not select a different app.\n\n## Partition the Action input\n\n| Field | Use in this family |\n|---|---|\n| `task_id` | Renders a stop or event-stream route segment |\n| `workflow_run_id` | Renders the workflow-run detail route segment |\n| `workflow_id` | Renders the pinned workflow-version route segment |\n| `form_token` | Renders a human-input form route segment |\n| `user` | Enters JSON for stop, run, and form submission, or query for event resume |\n| `query` | Supplies workflow-log filters or event-resume controls |\n| `body` | Supplies workflow inputs or human-input form values |\n\nEach rendered path value contains 1 to 512 bytes without control characters.\nThe connector percent-encodes each value as one path segment.\n\n`user` contains 1 to 256 bytes without control characters. The connector\ninserts it into the required location and rejects a conflicting query or body\nvalue.\n\n`query` has at most 128 keys and at most 256 scalar values per array. `body`\nhas at most 512 properties, and its encoded JSON cannot exceed 8 MiB.\n\n## Inspect workflow runs and logs\n\nUse `workflow.run.get` with the provider workflow-run ID:\n\n```json\n{\n  \"workflow_run_id\": \"0190c42f-2d5a-7000-8000-000000000201\"\n}\n```\n\nThe result can include `id`, `workflow_id`, `status`, `inputs`, `outputs`,\n`error`, step and token totals, timestamps, and elapsed time. A paused run\nreturns an empty `outputs` object until execution continues.\n\nThis read is app-scoped, not end-user scoped. The pinned route checks the app\nand tenant but has no `user` input. Treat its inputs, outputs, and errors as\nconfidential PII-bearing data.\n\n`workflow.log.list` accepts these optional query fields:\n\n| Field | Constraint |\n|---|---|\n| `keyword` | Provider log search term |\n| `status` | `succeeded`, `failed`, or `stopped` |\n| `created_at__before` | ISO 8601 timestamp |\n| `created_at__after` | ISO 8601 timestamp |\n| `created_by_end_user_session_id` | End-user session filter |\n| `created_by_account` | Account ID filter |\n| `page` | 1 to 99,999; default 1 |\n| `limit` | 1 to 100; default 20 |\n\nLog records can include workflow-run status, errors, creator details, and\nexecution details. This operation is also app-scoped and can expose data from\nmultiple end users under that app.\n\n## Run one published workflow version\n\nSelect `workflow.run_by_id` when the task requires a specific published\nworkflow version rather than the app's default invocation alias:\n\n```json\n{\n  \"workflow_id\": \"0190c42f-2d5a-7000-8000-000000000202\",\n  \"user\": \"tenant-user-0190\",\n  \"body\": {\n    \"inputs\": {\n      \"topic\": \"quarterly forecast\"\n    },\n    \"files\": []\n  }\n}\n```\n\nThe pinned provider requires `inputs`; `files` is optional. A file input uses\neither a provider upload ID or an authorized remote URL according to the\nworkflow's published parameter definition.\n\nThe connector controls `response_mode`. Its streaming execution path requests\nSSE, while its synchronous path requests a blocking response. A caller-supplied\n`response_mode` does not override that decision.\n\nThis operation invokes models and changes provider execution state. It is\nhigh-risk, requires tenant-policy approval and an idempotency key, publishes no\nsafe retry, and has no rollback capability.\n\n## Stop an active task\n\nAll three stop operations require the task ID and the same stable Dify user\nused to start generation:\n\n```json\n{\n  \"task_id\": \"task-0190c42f\",\n  \"user\": \"tenant-user-0190\"\n}\n```\n\nChoose the stop suffix that matches the configured app mode. The connector\ndoes not infer the task family from the task ID.\n\nThe pinned completion and chat routes pass the user identity to Dify task\ncontrol. The pinned workflow route requires a user field but sends its stop\ncommands without checking task ownership against that user. Approval must\ntherefore confirm the exact app and workflow task.\n\nA successful stop response means Dify accepted the command. Confirm the\nterminal state through the workflow-run read or a terminal stream event before\nreleasing task correlation data.\n\n## Resume workflow events\n\nUse `workflow.event.stream` after a dropped connection or a human-input pause:\n\n```json\n{\n  \"task_id\": \"0190c42f-2d5a-7000-8000-000000000203\",\n  \"user\": \"tenant-user-0190\",\n  \"query\": {\n    \"include_state_snapshot\": true,\n    \"continue_on_pause\": true\n  }\n}\n```\n\nThe provider verifies the app, tenant, end-user creator role, and exact end\nuser. A finished run emits one `workflow_finished` event and closes.\n\n`include_state_snapshot` replays a persisted status summary before new events.\n`continue_on_pause` keeps the stream open across consecutive\n`workflow_paused` events. Both fields default to `false`.\n\nThe connector limits each SSE frame to 1 MiB, the stream to 10,000 parsed\nevents, and the total response to the configured response bound. A stream that\ncloses without a terminal event is a connector error, not successful\ncompletion.\n\n## Read and submit a human-input form\n\n`human_input_form.get` requires only `form_token`. The pinned provider returns\nthe form only when it belongs to the selected app and tenant and uses an\nallowed Service API recipient type.\n\nThe response contains `form_content`, input definitions,\n`resolved_default_values`, `user_actions`, and an optional expiration time.\nThe form token normally comes from a `human_input_required` event.\n\nSubmit the selected action and values with `human_input_form.submit`:\n\n```json\n{\n  \"form_token\": \"form-token-0190\",\n  \"user\": \"tenant-user-0190\",\n  \"body\": {\n    \"inputs\": {\n      \"decision\": \"approve\"\n    },\n    \"action\": \"continue\"\n  }\n}\n```\n\nThe `action` value must match an ID from `user_actions`. Each `inputs` key must\nmatch the form definition. File values use Dify's local-upload or remote-URL\nform mapping.\n\nForms are one-shot. The first accepted response wins, regardless of which\nend user submits it, and an expired form cannot resume the workflow. Submission\ntherefore requires approval, one immutable input, and no automatic replay.\n\n## Interpret results and cancellation\n\nSynchronous JSON operations complete with the generic connector envelope:\n\n```json\n{\n  \"http_status\": 200,\n  \"body\": {\n    \"result\": \"success\"\n  },\n  \"content_type\": \"application/json\",\n  \"provider_request_id\": null\n}\n```\n\nFor streaming execution, the connector emits each parsed provider event as an\nAIP stream chunk. The terminal Action output contains the final event, or an\nassembled answer with that event.\n\n`human_input_required` and `workflow_paused` produce an AIP\n`requires_human` result. An `error` event, or a non-succeeded\n`workflow_finished` event, produces a failed Action result.\n\nDuring streaming, the connector records a provider task ID only after Dify\nemits it. Cancellation before that point drops the request but cannot confirm a\nremote stop. Later cancellation sends the mode-specific stop request.\n\n## Recover safely\n\n| Observation | Decision |\n|---|---|\n| Path, user, query, or body is rejected before dispatch | Correct the same bounded request without claiming provider state |\n| Workflow version is missing or still a draft | Select a published version; do not retry the rejected ID |\n| Run or log read is unauthorized | Re-establish the app credential and tenant route without printing secrets |\n| Event resume cannot match the end user | Recover the original task and user mapping before another stream |\n| SSE closes before a terminal event | Treat completion as unknown and inspect the workflow run |\n| Cancellation occurs before any task ID arrives | Record that remote stop is unconfirmed and inspect provider state |\n| Stop returns success but no terminal evidence exists | Poll the run or resume events; do not report completion |\n| Form is expired or already submitted | Do not replay; inspect workflow state and preserve the first-response evidence |\n| Run, stop, or form submission has an ambiguous transport outcome | Treat provider state as uncertain and reconcile through authoritative reads |\n| Returned run or log data crosses the intended app or tenant | Stop traffic and treat the event as an isolation incident |\n\nAll five POST operations require approval and a non-blank Action idempotency\nkey of at most 512 bytes. The AIP reservation is tenant-scoped for 24 hours,\nbut it does not prove provider deduplication.\n\n## Related documentation\n\n- [Dify capability index](README.md)\n- [Dify connector overview](../README.md)\n- [Dify connector configuration](../reference/configuration.md)\n- [Authentication and credential scopes](../getting-started/authentication-and-credential-scopes.md)\n- [Errors and retry decisions](../../../reference/errors.md)\n",
    "text": "Dify workflows, streaming, and human input\n\nUse this family to inspect workflow runs and logs, execute a published workflow\nversion, stop active generation, resume workflow events, and answer a paused\nhuman-input form. The nine operations use one configured Dify app credential.\n\nTask control is not proof of terminal provider state. Preserve the app, end\nuser, task, workflow run, and form identities until a read or terminal event\nestablishes the outcome.\n\nChoose an operation\n\n| Operation suffix | Method and route | Connector modes | Result | Policy |\n\n| completion.stop | POST /v1/completion-messages/{taskid}/stop | completion | JSON | Medium mutation; approval and key required |\n| chat.stop | POST /v1/chat-messages/{taskid}/stop | Four chat-like modes | JSON | Medium mutation; approval and key required |\n| workflow.run.get | GET /v1/workflows/run/{workflowrunid} | workflow, advanced-chat | JSON | Low-risk read; retry supported |\n| workflow.runbyid | POST /v1/workflows/{workflowid}/run | workflow | SSE or blocking JSON | High mutation; approval and key required |\n| workflow.stop | POST /v1/workflows/tasks/{taskid}/stop | workflow | JSON | Medium mutation; approval and key required |\n| workflow.log.list | GET /v1/workflows/logs | workflow, advanced-chat | JSON | Low-risk read; retry supported |\n| workflow.event.stream | GET /v1/workflow/{taskid}/events | workflow | SSE | Low-risk read; retry supported |\n| humaninputform.get | GET /v1/form/humaninput/{formtoken} | All six app modes | JSON | Low-risk read; retry supported |\n| humaninputform.submit | POST /v1/form/humaninput/{formtoken} | All six app modes | JSON | Medium mutation; approval and key required |\n\nThe four chat-like modes are chat, advanced-chat, agent-chat, and\nagent. Connector discovery exposes workflow.event.stream only for\nworkflow, although the pinned provider route also accepts advanced-chat.\n\nThe capability template is:\n\ncap:dify::\n\nUse tenant discovery to obtain the exact capability ID. A task ID, workflow\nrun ID, workflow version ID, or form token does not select a different app.\n\nPartition the Action input\n\n| Field | Use in this family |\n\n| taskid | Renders a stop or event-stream route segment |\n| workflowrunid | Renders the workflow-run detail route segment |\n| workflowid | Renders the pinned workflow-version route segment |\n| formtoken | Renders a human-input form route segment |\n| user | Enters JSON for stop, run, and form submission, or query for event resume |\n| query | Supplies workflow-log filters or event-resume controls |\n| body | Supplies workflow inputs or human-input form values |\n\nEach rendered path value contains 1 to 512 bytes without control characters.\nThe connector percent-encodes each value as one path segment.\n\nuser contains 1 to 256 bytes without control characters. The connector\ninserts it into the required location and rejects a conflicting query or body\nvalue.\n\nquery has at most 128 keys and at most 256 scalar values per array. body\nhas at most 512 properties, and its encoded JSON cannot exceed 8 MiB.\n\nInspect workflow runs and logs\n\nUse workflow.run.get with the provider workflow-run ID:\n\n{\n  \"workflowrunid\": \"0190c42f-2d5a-7000-8000-000000000201\"\n}\n\nThe result can include id, workflowid, status, inputs, outputs,\nerror, step and token totals, timestamps, and elapsed time. A paused run\nreturns an empty outputs object until execution continues.\n\nThis read is app-scoped, not end-user scoped. The pinned route checks the app\nand tenant but has no user input. Treat its inputs, outputs, and errors as\nconfidential PII-bearing data.\n\nworkflow.log.list accepts these optional query fields:\n\n| Field | Constraint |\n\n| keyword | Provider log search term |\n| status | succeeded, failed, or stopped |\n| createdatbefore | ISO 8601 timestamp |\n| createdatafter | ISO 8601 timestamp |\n| createdbyendusersessionid | End-user session filter |\n| createdbyaccount | Account ID filter |\n| page | 1 to 99,999; default 1 |\n| limit | 1 to 100; default 20 |\n\nLog records can include workflow-run status, errors, creator details, and\nexecution details. This operation is also app-scoped and can expose data from\nmultiple end users under that app.\n\nRun one published workflow version\n\nSelect workflow.runbyid when the task requires a specific published\nworkflow version rather than the app's default invocation alias:\n\n{\n  \"workflowid\": \"0190c42f-2d5a-7000-8000-000000000202\",\n  \"user\": \"tenant-user-0190\",\n  \"body\": {\n    \"inputs\": {\n      \"topic\": \"quarterly forecast\"\n    },\n    \"files\": []\n  }\n}\n\nThe pinned provider requires inputs; files is optional. A file input uses\neither a provider upload ID or an authorized remote URL according to the\nworkflow's published parameter definition.\n\nThe connector controls responsemode. Its streaming execution path requests\nSSE, while its synchronous path requests a blocking response. A caller-supplied\nresponsemode does not override that decision.\n\nThis operation invokes models and changes provider execution state. It is\nhigh-risk, requires tenant-policy approval and an idempotency key, publishes no\nsafe retry, and has no rollback capability.\n\nStop an active task\n\nAll three stop operations require the task ID and the same stable Dify user\nused to start generation:\n\n{\n  \"taskid\": \"task-0190c42f\",\n  \"user\": \"tenant-user-0190\"\n}\n\nChoose the stop suffix that matches the configured app mode. The connector\ndoes not infer the task family from the task ID.\n\nThe pinned completion and chat routes pass the user identity to Dify task\ncontrol. The pinned workflow route requires a user field but sends its stop\ncommands without checking task ownership against that user. Approval must\ntherefore confirm the exact app and workflow task.\n\nA successful stop response means Dify accepted the command. Confirm the\nterminal state through the workflow-run read or a terminal stream event before\nreleasing task correlation data.\n\nResume workflow events\n\nUse workflow.event.stream after a dropped connection or a human-input pause:\n\n{\n  \"taskid\": \"0190c42f-2d5a-7000-8000-000000000203\",\n  \"user\": \"tenant-user-0190\",\n  \"query\": {\n    \"includestatesnapshot\": true,\n    \"continueonpause\": true\n  }\n}\n\nThe provider verifies the app, tenant, end-user creator role, and exact end\nuser. A finished run emits one workflowfinished event and closes.\n\nincludestatesnapshot replays a persisted status summary before new events.\ncontinueonpause keeps the stream open across consecutive\nworkflowpaused events. Both fields default to false.\n\nThe connector limits each SSE frame to 1 MiB, the stream to 10,000 parsed\nevents, and the total response to the configured response bound. A stream that\ncloses without a terminal event is a connector error, not successful\ncompletion.\n\nRead and submit a human-input form\n\nhumaninputform.get requires only formtoken. The pinned provider returns\nthe form only when it belongs to the selected app and tenant and uses an\nallowed Service API recipient type.\n\nThe response contains formcontent, input definitions,\nresolveddefaultvalues, useractions, and an optional expiration time.\nThe form token normally comes from a humaninputrequired event.\n\nSubmit the selected action and values with humaninputform.submit:\n\n{\n  \"formtoken\": \"form-token-0190\",\n  \"user\": \"tenant-user-0190\",\n  \"body\": {\n    \"inputs\": {\n      \"decision\": \"approve\"\n    },\n    \"action\": \"continue\"\n  }\n}\n\nThe action value must match an ID from useractions. Each inputs key must\nmatch the form definition. File values use Dify's local-upload or remote-URL\nform mapping.\n\nForms are one-shot. The first accepted response wins, regardless of which\nend user submits it, and an expired form cannot resume the workflow. Submission\ntherefore requires approval, one immutable input, and no automatic replay.\n\nInterpret results and cancellation\n\nSynchronous JSON operations complete with the generic connector envelope:\n\n{\n  \"httpstatus\": 200,\n  \"body\": {\n    \"result\": \"success\"\n  },\n  \"contenttype\": \"application/json\",\n  \"providerrequestid\": null\n}\n\nFor streaming execution, the connector emits each parsed provider event as an\nAIP stream chunk. The terminal Action output contains the final event, or an\nassembled answer with that event.\n\nhumaninputrequired and workflowpaused produce an AIP\nrequireshuman result. An error event, or a non-succeeded\nworkflowfinished event, produces a failed Action result.\n\nDuring streaming, the connector records a provider task ID only after Dify\nemits it. Cancellation before that point drops the request but cannot confirm a\nremote stop. Later cancellation sends the mode-specific stop request.\n\nRecover safely\n\n| Observation | Decision |\n\n| Path, user, query, or body is rejected before dispatch | Correct the same bounded request without claiming provider state |\n| Workflow version is missing or still a draft | Select a published version; do not retry the rejected ID |\n| Run or log read is unauthorized | Re-establish the app credential and tenant route without printing secrets |\n| Event resume cannot match the end user | Recover the original task and user mapping before another stream |\n| SSE closes before a terminal event | Treat completion as unknown and inspect the workflow run |\n| Cancellation occurs before any task ID arrives | Record that remote stop is unconfirmed and inspect provider state |\n| Stop returns success but no terminal evidence exists | Poll the run or resume events; do not report completion |\n| Form is expired or already submitted | Do not replay; inspect workflow state and preserve the first-response evidence |\n| Run, stop, or form submission has an ambiguous transport outcome | Treat provider state as uncertain and reconcile through authoritative reads |\n| Returned run or log data crosses the intended app or tenant | Stop traffic and treat the event as an isolation incident |\n\nAll five POST operations require approval and a non-blank Action idempotency\nkey of at most 512 bytes. The AIP reservation is tenant-scoped for 24 hours,\nbut it does not prove provider deduplication.\n\nRelated documentation\n• Dify capability index (README.md)\n• Dify connector overview (../README.md)\n• Dify connector configuration (../reference/configuration.md)\n• Authentication and credential scopes (../getting-started/authentication-and-credential-scopes.md)\n• Errors and retry decisions (../../../reference/errors.md)\n"
  },
  "integrity": {
    "algorithm": "sha256",
    "sourceDigest": "d9fb80cf4c4a2af53f036ec738675fe749eefea4926384c03c8cea53ba86ae26"
  }
}
