Your First Agent
Build an AI agent inside a workflow: register tools, create a workflow with a ReAct loop, execute it, inspect the paused agent trace, resume it with human input, and confirm the parent workflow completed.
Prerequisites
A running Hyphen instance at https://your-hyphen.example.com with an LLM API key configured. All examples use X-Org-Id: tutorial-org.
Store your LLM key if you haven't already:
curl -X POST https://your-hyphen.example.com/org-config \
-H "X-Org-Id: tutorial-org" \
-H "Content-Type: application/json" \
-d '{ "key": "api:llm_api_key", "value": "sk-your-openai-key" }'
Step 1: Register Tools
Agents need tools to work with. Register an HTTP action and an LLM action:
# An HTTP action that looks up order details
curl -X POST https://your-hyphen.example.com/actions \
-H "X-Org-Id: tutorial-org" \
-H "Content-Type: application/json" \
-d '{
"action_name": "lookup_order",
"kind": "http",
"url": "https://httpbin.org/anything/orders",
"http_method": "GET",
"passthrough": true
}'
# An LLM action that drafts a customer response
curl -X POST https://your-hyphen.example.com/actions \
-H "X-Org-Id: tutorial-org" \
-H "Content-Type: application/json" \
-d '{
"action_name": "draft_response",
"kind": "llm",
"template": "Draft a professional, empathetic response to this customer issue:\n\nIssue: {{issue}}\nOrder details: {{order_details}}\n\nKeep it under 3 sentences.",
"model": "gpt-4o-mini",
"max_tokens": 256
}'
Step 2: Create the Agent Workflow
Create a workflow with an embedded ReAct loop. For this first example, the objective is written as a concrete case so the agent can reason from explicit facts and use the registered tools:
curl -X POST https://your-hyphen.example.com/workflows \
-H "X-Org-Id: tutorial-org" \
-H "Content-Type: application/json" \
-d '{
"name": "customer_issue_agent",
"definition": {
"actions": [
{
"type": "loop",
"properties": {
"mode": "react",
"objective": "Handle this customer issue: the customer says they were charged twice for order ORD-12345 and wants a $150 refund. First call lookup_order with query.order_id set to ORD-12345. Then use the returned order details to draft a short customer response. Because the requested refund is over $100, pause for human approval before completing. After human guidance arrives, complete with the drafted response, the approval outcome, and a confidence score.",
"tools": [
{ "type": "action", "name": "lookup_order" },
{ "type": "action", "name": "draft_response" }
],
"model": "gpt-4o",
"max_iterations": 8,
"on_stuck": {
"iterations": 3,
"action": "escalate"
},
"result_key": "agent_result"
}
}
]
}
}'
What this does: The workflow contains a ReAct loop step. The agent receives an objective in natural language and a list of tools. It reasons step by step — thinking about what to do, choosing a tool, observing the result, and repeating until it calls __complete__. In this example, the objective explicitly tells the agent to pause for human approval before finishing because the refund amount is over $100.
Step 3: Execute the Workflow
curl -X POST https://your-hyphen.example.com/workflows/WORKFLOW_ID/execute \
-H "X-Org-Id: tutorial-org" \
-H "Content-Type: application/json" \
-d '{
"input": {}
}'
Save the returned run-... id as RUN_ID.
Step 4: Check the Parent Workflow Run
curl https://your-hyphen.example.com/runs/RUN_ID/status \
-H "X-Org-Id: tutorial-org"
For an embedded agent, the parent workflow run usually stays running while the ReAct loop is active or waiting for human input. You should see the loop step in the run status, but not the full agent reasoning trace yet.
A typical response looks like this:
{
"id": "run-...",
"status": "running",
"steps": [
{
"index": 0,
"type": "loop",
"status": "processing"
}
]
}
Step 5: Capture the agent_run_id and Inspect the Paused Agent
The embedded ReAct loop creates a separate AgentRun. The most reliable way to capture its id is from the webhook stream:
loop.startedagent.started
Those webhook payloads include agent_run_id for the embedded loop.
If you are testing in a clean tutorial org and this is the only active paused agent, you can also fetch the most recent paused agent run:
curl "https://your-hyphen.example.com/agents?status=paused&limit=1" \
-H "X-Org-Id: tutorial-org"
Once you have AGENT_RUN_ID, inspect the agent status and include the current trace:
curl "https://your-hyphen.example.com/agents/AGENT_RUN_ID/status?include_trace=true" \
-H "X-Org-Id: tutorial-org"
A typical paused response looks like this:
{
"agent_run_id": "agent-wf-...",
"status": "paused",
"iterations": 3,
"reasoning_trace": [
{
"iteration": 0,
"thought": "I should look up the order details first.",
"action": "lookup_order",
"action_input": {
"query": {
"order_id": "ORD-12345"
}
},
"observation": {
"url": "https://httpbin.org/anything/orders?order_id=ORD-12345",
"method": "GET"
}
},
{
"iteration": 1,
"thought": "Now I can draft a customer response using the order details I just retrieved.",
"action": "draft_response",
"action_input": {
"issue": "Customer reports a duplicate charge and is requesting a $150 refund.",
"order_details": "..."
},
"observation": {
"llm_result": "I’m sorry about the duplicate charge on your order. I’ve drafted the response and flagged the $150 refund request for approval."
}
},
{
"iteration": 2,
"thought": "Because the requested refund is over $100, I need human approval before I complete the task.",
"action": "__pause_for_human__",
"action_input": {
"question": "The customer is requesting a $150 refund for order ORD-12345. Should I proceed with the approved refund response?",
"options": ["Approve", "Deny", "Need more information"],
"context_summary": "Order details retrieved. Draft response prepared.",
"urgency": "medium"
}
}
]
}
Step 6: Resume the Agent with Human Input
Provide the human decision:
curl -X POST https://your-hyphen.example.com/agents/AGENT_RUN_ID/resume \
-H "X-Org-Id: tutorial-org" \
-H "Content-Type: application/json" \
-d '{
"human_input": "Approved. Keep the response concise and note that the refund will be handled by the operations team.",
"approved": true
}'
The embedded agent is queued again, continues from the paused checkpoint, and then hands its result back to the parent workflow.
Step 7: Read the Final Workflow Result
After the agent resumes and completes, check the parent workflow again:
curl https://your-hyphen.example.com/runs/RUN_ID/status \
-H "X-Org-Id: tutorial-org"
A completed workflow run will include the embedded agent result under agent_result:
{
"status": "completed",
"context": {
"agent_result": {
"status": "completed",
"answer": "Customer response drafted. The $150 refund request was approved and flagged for manual handling by the operations team.",
"confidence": 0.95,
"iterations": 4
}
}
}
The confidence score comes from the agent's final __complete__ call, and agent_result is the value written back into workflow context using the loop step's result_key.
Step 8: View the Complete Agent Trace
For the full audit trail, including iterations before and after the pause:
curl https://your-hyphen.example.com/agents/AGENT_RUN_ID/trace \
-H "X-Org-Id: tutorial-org"
This returns the full reasoning trace for the embedded agent run.
What You Built
A workflow with an embedded AI agent that:
- Reasons through a customer issue step by step
- Uses tools — looking up order data and drafting responses
- Pauses for human approval before completing a higher-risk task
- Resumes with human guidance incorporated into the next iteration
- Writes back a final answer and confidence score into workflow context
Key concepts demonstrated:
| Concept | How It Appeared |
|---|---|
| ReAct loop | Agent thinks → acts → observes → repeats |
| Tool usage | lookup_order (HTTP), draft_response (LLM) |
| Human escalation | __pause_for_human__ inside the embedded agent loop |
| Reasoning trace | Iteration-by-iteration trace on the AgentRun |
| Confidence scoring | Final answer includes a confidence score |
| Workflow handoff | Agent result stored under agent_result in the parent workflow context |
Next: Explore the templates for production-ready patterns, or read the agent deployment patterns guide to learn about agents as workflow triggers and orchestrators.