Skip to main content

Configure Your Workflow

Agentic workflows follow a fixed two-layer structure. The outer layer handles HTTP I/O. The inner layer runs the agent. Both the Chat Completions and the Responses API inject the same two fields into the outer layer, so a single workflow design works with either endpoint.

Finding your workflow ID

Both API endpoints require a numeric workflow id in the path (/agent/:id/...). Retrieve the list of your published workflows:

GET /workflows
Authorization: Bearer <your-access-token>
curl -sS \
-H "Authorization: Bearer <your-access-token>" \
https://api.alien.club/workflows

The response is {"success":true,"data":[...]} where each entry has id, name, slug, type, and other fields.

note

Only workflows with "type": "streaming" are compatible with the Chat Completions and Responses API endpoints. Workflows of type preset, ai-preset, or group-preset are not exposed through these APIs.

What the platform injects

Before dispatching any job, both API endpoints call injectInputIntoWorkflowNodes, which sets the httpRequest node's input body to:

{
"user_prompt": "<the resolved prompt string>",
"session_id": "<session identifier for this conversation turn>",
"model": "<the model string from the request body>"
}

user_prompt is the text the caller wants the agent to process.

session_id identifies the conversation. The value differs between APIs:

  • Chat Completions — the conversation_id from the request body (generated if omitted).
  • Responses API — resolved from previous_response_id via the server-side session store; generated on first turn.

model is forwarded verbatim from the request body. Wire it through to your deepAgent node so callers can select the upstream LLM per request without republishing the workflow.

Everything else the workflow does is under your control.

Graph structure

The recommended outer graph is three nodes:

Inside the aiAgent node, the inner graph is:

httpRequest node

The httpRequest node is a pass-through. After injection it emits results.user_prompt and results.session_id, referenced downstream as @httpRequest-0.user_prompt and @httpRequest-0.session_id.

No explicit params are required — the node accepts any JSON dict and emits it as-is.

agentInput node

agentInput is the bridge between the outer HTTP layer and the inner agent subgraph. It builds the messages array and forwards session_id, model, and user_prompt to the agent runtime.

The critical detail is isAttachedToInputNode: true on params that cross the aiAgent boundary. Without this flag, expressions that reference outer nodes are not resolved inside a nested subgraph.

{
"id": "agentInput-3",
"type": "agentInput",
"data": {
"params": {
"user_prompt": {
"value": "@httpRequest-0.user_prompt",
"isExpression": true,
"isAttachedToInputNode": true
},
"session_id": {
"value": "@httpRequest-0.session_id",
"isExpression": true,
"isAttachedToInputNode": true
},
"model": {
"value": "@httpRequest-0.model",
"isExpression": true,
"isAttachedToInputNode": true
},
"system_prompt": {
"value": "You are a helpful assistant.",
"isExpression": false,
"isAttachedToInputNode": false
}
}
}
}

deepAgent node

deepAgent receives the compiled messages array, session_id, and model from agentInput, plus the system prompt. model is dynamic — it flows from the request body through httpRequest-0agentInput-3deepAgent-4, so callers control the upstream LLM per request. Set streaming to true for all agentic endpoints — non-streaming mode is only for short synchronous pipelines.

{
"id": "deepAgent-4",
"type": "deepAgent",
"data": {
"params": {
"model": {
"value": "@agentInput-3.model",
"isExpression": true,
"isAttachedToInputNode": false
},
"system_prompt": {
"value": "@agentInput-3.system_prompt",
"isExpression": true,
"isAttachedToInputNode": false
},
"messages": {
"value": "@agentInput-3.messages",
"isExpression": true,
"isAttachedToInputNode": false
},
"streaming": {
"value": true,
"isExpression": false,
"isAttachedToInputNode": false
}
}
}
}

agentOutput node

agentOutput extracts the final answer and the session_id produced by the agent runtime. The session_id output from deepAgent is the one to preserve — it reflects any in-run state mutations made by the agent.

{
"id": "agentOutput-5",
"type": "agentOutput",
"data": {
"params": {
"answer": {
"value": "@deepAgent-4.answer",
"isExpression": true,
"isAttachedToInputNode": false
},
"session_id": {
"value": "@deepAgent-4.sessionId",
"isExpression": true,
"isAttachedToInputNode": false
}
}
}
}

httpResponse node

httpResponse is the exit point. It collects fields from the aiAgent node's output (which surfaces agentOutput's values) and returns them to the API caller.

answer carries the agent's text response. session_id carries the session identifier — the Chat Completions API reads it back to populate x_alien.conversation_id on the response; the Responses API reads it to populate session_id in the response store for next-turn linking.

{
"id": "httpResponse-2",
"type": "httpResponse",
"data": {
"params": {
"answer": {
"value": "@aiAgent-1.answer",
"isExpression": true,
"isAttachedToInputNode": false
},
"session_id": {
"value": "@aiAgent-1.session_id",
"isExpression": true,
"isAttachedToInputNode": false
}
}
}
}

Edges

Four edges wire the outer graph:

[
{ "id": "e0", "source": "httpRequest-0", "target": "aiAgent-1", "type": "flow" },
{ "id": "e1", "source": "aiAgent-1", "target": "httpResponse-2","type": "flow" }
]

Two edges wire the inner graph (stored in aiAgent-1.data.workflow.edges):

[
{ "id": "e2", "source": "agentInput-3", "target": "deepAgent-4", "type": "flow" },
{ "id": "e3", "source": "deepAgent-4", "target": "agentOutput-5", "type": "flow" }
]

Complete outer-graph example

{
"nodes": [
{
"id": "httpRequest-0",
"type": "httpRequest",
"data": {
"label": "HTTP Request",
"is_input": true,
"params": {}
},
"position": { "x": 0, "y": 0 }
},
{
"id": "aiAgent-1",
"type": "aiAgent",
"data": {
"label": "AI Agent",
"workflow": {
"nodes": [ /* agentInput-3, deepAgent-4, agentOutput-5 as above */ ],
"edges": [
{ "id": "e2", "source": "agentInput-3", "target": "deepAgent-4", "type": "flow" },
{ "id": "e3", "source": "deepAgent-4", "target": "agentOutput-5", "type": "flow" }
]
},
"params": {}
},
"position": { "x": 300, "y": 0 }
},
{
"id": "httpResponse-2",
"type": "httpResponse",
"data": {
"label": "HTTP Response",
"is_output": true,
"params": {
"answer": {
"value": "@aiAgent-1.answer",
"isExpression": true,
"isAttachedToInputNode": false
},
"session_id": {
"value": "@aiAgent-1.session_id",
"isExpression": true,
"isAttachedToInputNode": false
}
}
},
"position": { "x": 600, "y": 0 }
}
],
"edges": [
{ "id": "e0", "source": "httpRequest-0", "target": "aiAgent-1", "type": "flow" },
{ "id": "e1", "source": "aiAgent-1", "target": "httpResponse-2", "type": "flow" }
]
}

Adding subagents and tools

Subagents attach to deepAgent-4 via agent edges in the inner graph. MCP tool servers attach via tool edges. These edges do not affect execution order — DeepAgentCompiler reads them to assemble the agent hierarchy. See deepAgent and subagent for per-node details.

See also