Skip to content

Dify Integration

PyHall WCP — Dify Workflow Governance Integration

Insert a pyhall routing decision into any Dify workflow. Governed decisions are immutable, signed, and logged before any sensitive tool or LLM call executes.

What you can do

  • Block unauthorized capabilities — use IF/ELSE after the HTTP node to halt on denied: true
  • Capture audit proof — forward decision_id and artifact_hash to downstream nodes
  • Support any Dify app type — Chatflow, Workflow, Agent, and Chatbot all support HTTP Request nodes
  • No code required — the HTTP Request node handles auth headers and JSON body natively
  • Python fallback — use a Code node if you need preprocessing or dynamic capability IDs

Option A — HTTP Request node (no-code)

Insert an HTTP Request node in your Dify workflow before any sensitive step.

Node configuration

FieldValue
MethodPOST
URLhttp://localhost:8765/api/route (or your Hall Server URL)
AuthorizationBearer → value: your HALL_SESSION_TOKEN
Content-Typeapplication/json

Request body (JSON)

{
"capability_id": "{{#sys.query#}}",
"worker_id": "wrk_abc123",
"env": "prod",
"data_label": "INTERNAL",
"tenant_id": "org.acme"
}

Replace "{{#sys.query#}}" with a static capability ID or a variable reference from an earlier node — for example {{#node.capability_selector.output.capability_id#}}.

Variable references from the HTTP response

Dify maps the JSON response body into node output variables automatically. Reference them in downstream nodes:

VariablePathExample value
decision_idbody.decision_iddec_7f3a...
deniedbody.deniedtrue or false
selected_worker_species_idbody.selected_worker_species_idws_llm_basic
artifact_hashbody.artifact_hashsha256:4c2a...

IF/ELSE branch after the HTTP node

Add an IF/ELSE node immediately after the HTTP Request node:

  • IF: {{#http_node.body.denied#}} == false → continue to the governed tool
  • ELSE: end the workflow or return an error message to the user
[HTTP Request: pyhall /api/route]
|
[IF/ELSE]
denied == false?
/ \
[YES] [NO]
Continue End / Error message

Option B — Python Code node

Use a Code node when you need to build the capability ID dynamically or handle errors explicitly before branching.

import requests
def main(worker_id: str, capability_id: str, tenant_id: str) -> dict:
"""
pyhall WCP governance check.
Returns decision fields for downstream nodes.
"""
HALL_URL = "http://localhost:8765/api/route"
HALL_TOKEN = "hst_your_token_here" # use Dify secret variable in production
try:
resp = requests.post(
HALL_URL,
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {HALL_TOKEN}",
},
json={
"capability_id": capability_id,
"worker_id": worker_id,
"env": "prod",
"data_label": "INTERNAL",
"tenant_id": tenant_id,
},
timeout=5,
)
resp.raise_for_status()
data = resp.json()
return {
"decision_id": data["decision_id"],
"denied": data["denied"],
"selected_worker_species_id": data["selected_worker_species_id"],
"artifact_hash": data["artifact_hash"],
}
except Exception as e:
# Fail closed — deny on any error
return {
"decision_id": "error",
"denied": True,
"selected_worker_species_id": "",
"artifact_hash": "",
}

Code node inputs:

NameTypeSource
worker_idStringupstream variable or static wrk_abc123
capability_idStringstart node variable or classifier output
tenant_idStringuser session context or static org.acme

Code node outputs: decision_id, denied, selected_worker_species_id, artifact_hash

After the Code node, add an IF/ELSE: denied == false → proceed.

Storing HALL_SESSION_TOKEN securely

In Dify, go to Settings → Secret Variables and add:

HALL_SESSION_TOKEN = hst_your_token_here

Reference it in the HTTP Request node Authorization field as {{HALL_SESSION_TOKEN}}. In Code nodes, inject it via the input variable panel — never hardcode tokens in workflow exports.

Environment variables

Terminal window
HALL_SESSION_TOKEN=hst_... # Hall Server session token
HALL_API_URL=http://localhost:8765 # Hall Server base URL
PYHALL_API_KEY=your-registry-key # Registry auth (for pyhall CLI, not Dify nodes)

Getting started

  1. Start your Hall Server: pyhall server start (local) or point to https://api.pyhall.dev
  2. In Dify, open your workflow and add an HTTP Request node before any sensitive tool
  3. Configure method POST, URL, and Authorization: Bearer <token> header
  4. Set the JSON body with your capability_id and worker_id
  5. Add an IF/ELSE node branching on body.denied == false
  6. Verify decisions in the Hall Server log: pyhall decision query --limit 20

Full documentation: https://pyhall.dev/introduction/ WCP specification: https://workerclassprotocol.dev/spec/ Registry API: https://api.pyhall.dev