> ## Documentation Index
> Fetch the complete documentation index at: https://hub.hcompany.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Run agents from n8n

> Run Computer-Use Agents from an n8n workflow over plain HTTP.

Computer-Use Agents work in [n8n](https://n8n.io) as a standard HTTP integration. There's no custom node to install: you authenticate with a header, create a session, and either poll for the result or receive a webhook when it finishes.

<Steps titleSize="h3">
  <Step id="create-a-credential" title="Create a credential">
    In n8n, go to **Credentials → Add Credential → Header Auth** and set:

    | Field | Value           |
    | ----- | --------------- |
    | Name  | `Authorization` |
    | Value | `Bearer hk-...` |

    Create the key at [platform.hcompany.ai/settings/api-keys](https://platform.hcompany.ai/settings/api-keys?product=computeruseagents\&source=docs). It's shown once, so copy it when you create it. A key is scoped to one organization.
  </Step>

  <Step id="start-a-session" title="Start a session">
    Add an **HTTP Request** node:

    | Setting           | Value                                        |
    | ----------------- | -------------------------------------------- |
    | Method            | `POST`                                       |
    | URL               | `https://agp.eu.hcompany.ai/api/v2/sessions` |
    | Authentication    | Header Auth (from step 1)                    |
    | Body Content Type | JSON                                         |

    Body:

    ```json Request body theme={null}
    {
      "agent": "h/web-surfer-flash",
      "messages": [
        {"type": "user_message", "message": "Find the top 3 trending repositories on GitHub today and report their names and star counts"}
      ]
    }
    ```

    `h/web-surfer-flash` is a built-in agent that comes with its own browser environment, so you can run a task without setting anything else up. To run your own agent, pass its name instead, or send an inline agent object; see [Create a session](/computer-use-agents/sessions/create) for the full body.

    The response returns the session `id` you'll use to poll for results:

    ```json Response theme={null}
    {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "status": {"status": "pending", "steps": 0},
      "agent_view_url": "https://platform.hcompany.ai/agents/sessions/a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "latest_answer": null
    }
    ```
  </Step>

  <Step id="poll-for-completion" title="Poll for completion">
    Add a second **HTTP Request** node in a loop:

    | Setting        | Value                                                              |
    | -------------- | ------------------------------------------------------------------ |
    | Method         | `GET`                                                              |
    | URL            | `https://agp.eu.hcompany.ai/api/v2/sessions/{{ $json.id }}/status` |
    | Authentication | Header Auth (from step 1)                                          |

    Check the `status` field. The session is done when status is `completed`, `failed`, `timed_out`, or `interrupted`. Any other value (`queued`, `pending`, `running`, `paused`, `idle`, `awaiting_tool_results`) means it's still going. Use an **If** node to branch on the status, and loop the "still running" branch back through a **Wait** node before hitting the status endpoint again. Two to five seconds is a good interval; back off to ten to fifteen for tasks that run several minutes.

    ```json Status response theme={null}
    {
      "status": "running",
      "error": null,
      "steps": 7
    }
    ```
  </Step>

  <Step id="read-the-answer" title="Read the answer">
    The status endpoint tells you when the run is done, but it doesn't carry the answer. Once the status is `completed`, add one more **HTTP Request** node to fetch the session and read `latest_answer`:

    | Setting        | Value                                                       |
    | -------------- | ----------------------------------------------------------- |
    | Method         | `GET`                                                       |
    | URL            | `https://agp.eu.hcompany.ai/api/v2/sessions/{{ $json.id }}` |
    | Authentication | Header Auth (from step 1)                                   |

    The `latest_answer` field holds the agent's final result.
  </Step>
</Steps>

## Import the full workflow

Rather than build the four nodes by hand, copy the JSON below and paste it into an n8n canvas (**⋯ menu → Import from clipboard**, or just paste onto an empty canvas). It wires up the create, wait, poll, and read steps as a loop: the **Wait** node pauses a few seconds, **Poll Status** checks the state, and the **If** node either reads the answer (once the status is terminal) or loops back to wait.

After importing, open each HTTP Request node and select your own Header Auth credential from step 1. The credential ID baked into the export won't match your instance, so n8n shows the nodes as needing a credential until you pick yours.

<Accordion title="n8n workflow JSON">
  ```json theme={null}
  {
    "nodes": [
      {
        "parameters": {},
        "type": "n8n-nodes-base.manualTrigger",
        "typeVersion": 1,
        "position": [0, 0],
        "id": "cddf1db5-ac4a-4020-907c-20039726f972",
        "name": "When clicking 'Execute workflow'"
      },
      {
        "parameters": {
          "method": "POST",
          "url": "https://agp.eu.hcompany.ai/api/v2/sessions",
          "authentication": "genericCredentialType",
          "genericAuthType": "httpHeaderAuth",
          "sendBody": true,
          "specifyBody": "json",
          "jsonBody": "{\n  \"agent\": \"h/web-surfer-flash\",\n  \"messages\": [\n    {\"type\": \"user_message\", \"message\": \"Find the top 3 trending repositories on GitHub today and report their names and star counts\"}\n  ]\n}",
          "options": {}
        },
        "type": "n8n-nodes-base.httpRequest",
        "typeVersion": 4.4,
        "position": [208, 0],
        "id": "afb14ac5-9686-44af-b0ff-7c6268defbb8",
        "name": "Start Session",
        "credentials": {
          "httpHeaderAuth": {
            "id": "REPLACE_WITH_YOUR_CREDENTIAL_ID",
            "name": "Header Auth account"
          }
        }
      },
      {
        "parameters": {
          "amount": 3,
          "unit": "seconds"
        },
        "type": "n8n-nodes-base.wait",
        "typeVersion": 1.1,
        "position": [416, 0],
        "id": "a1111111-1111-4111-8111-111111111111",
        "name": "Wait",
        "webhookId": "b2222222-2222-4222-8222-222222222222"
      },
      {
        "parameters": {
          "url": "=https://agp.eu.hcompany.ai/api/v2/sessions/{{ $('Start Session').item.json.id }}/status",
          "authentication": "genericCredentialType",
          "genericAuthType": "httpHeaderAuth",
          "options": {}
        },
        "type": "n8n-nodes-base.httpRequest",
        "typeVersion": 4.4,
        "position": [624, 0],
        "id": "cdff9632-065d-41a0-b71f-563d70c2eddf",
        "name": "Poll Status",
        "credentials": {
          "httpHeaderAuth": {
            "id": "REPLACE_WITH_YOUR_CREDENTIAL_ID",
            "name": "Header Auth account"
          }
        }
      },
      {
        "parameters": {
          "conditions": {
            "options": {
              "caseSensitive": true,
              "leftValue": "",
              "typeValidation": "strict",
              "version": 2
            },
            "conditions": [
              {
                "id": "c3333333-3333-4333-8333-333333333333",
                "leftValue": "={{ ['completed','failed','timed_out','interrupted'].includes($json.status) }}",
                "rightValue": "",
                "operator": {
                  "type": "boolean",
                  "operation": "true",
                  "singleValue": true
                }
              }
            ],
            "combinator": "and"
          },
          "options": {}
        },
        "type": "n8n-nodes-base.if",
        "typeVersion": 2.2,
        "position": [832, 0],
        "id": "d4444444-4444-4444-8444-444444444444",
        "name": "Session finished?"
      },
      {
        "parameters": {
          "url": "=https://agp.eu.hcompany.ai/api/v2/sessions/{{ $('Start Session').item.json.id }}",
          "authentication": "genericCredentialType",
          "genericAuthType": "httpHeaderAuth",
          "options": {}
        },
        "type": "n8n-nodes-base.httpRequest",
        "typeVersion": 4.4,
        "position": [1040, -96],
        "id": "72eccd6a-4d0e-4f55-9809-ba7708d8760b",
        "name": "Read Answer",
        "credentials": {
          "httpHeaderAuth": {
            "id": "REPLACE_WITH_YOUR_CREDENTIAL_ID",
            "name": "Header Auth account"
          }
        }
      }
    ],
    "connections": {
      "When clicking 'Execute workflow'": {
        "main": [[{ "node": "Start Session", "type": "main", "index": 0 }]]
      },
      "Start Session": {
        "main": [[{ "node": "Wait", "type": "main", "index": 0 }]]
      },
      "Wait": {
        "main": [[{ "node": "Poll Status", "type": "main", "index": 0 }]]
      },
      "Poll Status": {
        "main": [[{ "node": "Session finished?", "type": "main", "index": 0 }]]
      },
      "Session finished?": {
        "main": [
          [{ "node": "Read Answer", "type": "main", "index": 0 }],
          [{ "node": "Wait", "type": "main", "index": 0 }]
        ]
      }
    },
    "pinData": {},
    "meta": {}
  }
  ```
</Accordion>

The loop runs until the session reaches a terminal state; add a counter if you want a hard cap on the number of polls.

## Event-driven alternative

Instead of polling, use [Webhooks](/computer-use-agents/webhooks/overview) to get a callback when a session changes status. Add a **Webhook** trigger node in n8n, copy its Production URL, then register that URL for your organization with the [Create webhook](/computer-use-agents/webhooks/create) API. Subscribe to the events you care about, like `session.completed` and `session.failed`, or to `session.status_updated` for every transition (see the [event catalog](/computer-use-agents/webhooks/events)). n8n then receives a `POST` whenever a matching event fires, with `session_id`, `status`, and `previous_status` in the payload.

Deliveries are signed and retried with backoff, so the same event can arrive more than once. Verify the signature (see [Verifying deliveries](/computer-use-agents/webhooks/overview#verifying-deliveries)), skip event ids you've already processed, and treat the webhook as a trigger: fetch the session for the authoritative state.

The same pattern works with any tool that can make HTTP requests, such as Make, Zapier, Pipedream, or your own orchestrator.

## Next steps

<CardGroup cols={2}>
  <Card title="Create a session" icon="bolt" href="/computer-use-agents/sessions/create">
    The full session request body and options.
  </Card>

  <Card title="Session status" icon="signal" href="/computer-use-agents/sessions/status">
    States, step count, and the polling pattern.
  </Card>

  <Card title="Webhooks" icon="webhook" href="/computer-use-agents/webhooks/overview">
    Signed callbacks on status changes, and how to verify them.
  </Card>

  <Card title="SDKs" icon="code" href="/computer-use-agents/sdks">
    The typed Python and TypeScript clients and the hai CLI.
  </Card>
</CardGroup>
