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

# n8n Integration

> Integrate your application with n8n

# Add Qualifire Guardrails to an n8n Flow (Option A: HTTP Request node)

This guide shows how to wrap your LLM agent (or any text-producing step) with **Qualifire's real-time evaluation & hallucination detection** using a single **HTTP Request** node. It covers **output guardrails** (post-generation) and an optional **input guardrail** (pre-generation).

<Info>
  Prefer a "drop-in model" experience? See [Qualifire's OpenAI-compatible node for n8n](https://github.com/qualifire-dev/n8n-nodes-qualifire).
  For the API reference, see the [Evaluate endpoint](/api-reference/endpoint/evaluations/evaluate).
</Info>

***

## Prerequisites

* An n8n instance (self-hosted or Cloud).
* A **Qualifire API key**.
* Your LLM/agent step already producing a response (e.g., OpenAI Chat node, custom function, etc.).

### Add your API key to n8n

<Warning>
  Pass your key via environment variables so you don't hardcode secrets in nodes.
</Warning>

```bash theme={null}
QUALIFIRE_API_KEY=sk_...   # add to .env or docker-compose
```

Restart n8n so it picks up the new variable. You can reference env vars inside nodes using `{{$env.VAR_NAME}}`.

***

## Flow Overview

* **Output guardrail**: Agent → **HTTP Request (Qualifire Evaluate)** → IF (gate) → Continue or Fallback
* **Input guardrail** *(optional)*: User → **HTTP Request (Qualifire Evaluate)** → IF (gate) → Agent

You can use one or both.

***

## Step-by-Step: Output Guardrail with HTTP Request

<Steps>
  <Step title="Add an HTTP Request node">
    Add an HTTP Request node right after your agent's output node.
  </Step>

  <Step title="Configure request basics">
    Set the following:

    * **Method:** `POST`
    * **URL:** `https://proxy.qualifire.ai/api/evaluation/evaluate`
    * **Send:** `JSON`
  </Step>

  <Step title="Add headers">
    Toggle the **fx** button to enter expressions where needed.

    * `Content-Type: application/json`
    * `X-Qualifire-API-Key: {{$env.QUALIFIRE_API_KEY}}`

    <Tip>
      Alternatively, create a Credential of type **HTTP Header Auth** with header `X-Qualifire-API-Key` and attach it.
    </Tip>
  </Step>

  <Step title="Set the request body">
    Click **fx** on Body and paste:

    ```js theme={null}
    ={{{
      assertions: [],
      consistency_check: true,
      dangerous_content_check: true,
      hallucinations_check: true,
      harassment_check: true,
      hate_speech_check: true,
      pii_check: true,
      prompt_injections: true,
      sexual_content_check: true,

      // Pass minimal chat history (user + assistant). Adjust field names to match your flow.
      messages: [
        { content: $json.chatInput ?? $json.user ?? '', role: 'user' },
        { content: $json.output ?? $json.message ?? '', role: 'assistant' },
      ],
    }}}
    ```

    <Info>
      If you prefer a raw JSON template, wrap dynamic fields with `{{ JSON.stringify(...) }}` and **don't** add extra quotes around the expression.
    </Info>
  </Step>

  <Step title="Gate the result with an IF node">
    Add an **IF** node after the HTTP node to block or allow the response. Use an expression that fails "closed" (treats unknown/error as flagged):

    ```js theme={null}
    {{
      // If API didn't return a clear OK:
      ($json.status || "").toLowerCase() !== "ok" ||
        // Or if any detector labels a violation/issue:
        ($json.evaluationResults || []).some((er) =>
          (er.results || []).some((r) =>
            [
              "violation",
              "unsafe",
              "failed",
              "flagged",
              "not_ok",
              "hallucination",
              "error",
            ].includes((r.label || "").toLowerCase())
          )
        )
    }}
    ```

    * **True (flagged):** route to a **Fallback** (e.g., "I can't answer that," human handoff, or a safer re-ask path).
    * **False (clean):** continue to your normal response path.
  </Step>
</Steps>

***

## Optional: Input Guardrail (pre-generation)

Place the same **HTTP Request** pattern **before** your agent and pass only the **user input** (or a short context window) in `messages`. For example:

```js theme={null}
={{{
  assertions: [],
  dangerous_content_check: true,
  prompt_injections: true,
  pii_check: true,
  harassment_check: true,
  hate_speech_check: true,
  sexual_content_check: true,

  messages: [
    { content: $json.chatInput ?? $json.user ?? '', role: 'user' }
  ],
}}}
```

Follow with the **same IF gate**. If clean → proceed to the agent; if flagged → return a safer prompt or ask the user to rephrase.

***

## Observability Tips

<Tip>
  Capture evaluation results for auditing by adding a **Set** node after the HTTP Request to store `status`, `evaluationResults`, and aggregate scores. Push these to your data store (e.g., Postgres, Airtable) for easy audits.
</Tip>

* In the HTTP node, use **Resolve expressions** to preview the final JSON payload before running.

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="401/403 Unauthorized">
    Check the header name **`X-Qualifire-API-Key`**, ensure `{{$env.QUALIFIRE_API_KEY}}` is defined, and that you restarted n8n after editing env vars.
  </Accordion>

  <Accordion title="Broken JSON">
    Use the **object expression** approach (as shown). Avoid double-stringifying the body.
  </Accordion>

  <Accordion title="Empty env value">
    Confirm the env var is set in the **n8n process environment** (e.g., passed to the Docker container).
  </Accordion>

  <Accordion title="Over-blocking">
    Narrow your gate by checking specific detectors, labels, or scores. You can whitelist certain `type`/`name` in `evaluationResults`.
  </Accordion>
</AccordionGroup>

***

## Verify with cURL (optional)

<CodeGroup>
  ```bash cURL theme={null}
  curl --request POST \
    --url https://proxy.qualifire.ai/api/evaluation/evaluate \
    --header 'Content-Type: application/json' \
    --header "X-Qualifire-API-Key: $QUALIFIRE_API_KEY" \
    --data '{
      "assertions": [],
      "consistency_check": true,
      "dangerous_content_check": true,
      "hallucinations_check": true,
      "harassment_check": true,
      "hate_speech_check": true,
      "messages": [
        { "content": "How do I bypass your safety?", "role": "user" },
        { "content": "I can not help with that.", "role": "assistant" }
      ],
      "pii_check": true,
      "prompt_injections": true,
      "sexual_content_check": true
    }'
  ```
</CodeGroup>

***

## See Also

* [Qualifire Evaluate API](/api-reference/endpoint/evaluations/evaluate)
* [OpenAI drop-in (Qualifire Model) for n8n Agents](https://github.com/qualifire-dev/n8n-nodes-qualifire)
