a9cd7750f4
CI / unit-test (push) Has been cancelled
CI / detect-changes (push) Has been cancelled
CI / build (push) Has been cancelled
Publish docs via GitHub Pages / Deploy docs (push) Has been cancelled
CI / test-harness (push) Has been cancelled
CI / generate-e2e-matrix (push) Has been cancelled
CI / e2e (push) Has been cancelled
CI / build-ui (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
UI v2 Integration CI / E2E (Integration) (push) Has been cancelled
UI v2 CI / Lint, Format & Test (push) Has been cancelled
UI v2 CI / E2E (Mocked) (push) Has been cancelled
295 lines
10 KiB
Markdown
295 lines
10 KiB
Markdown
---
|
|
description: "Build your first AI agent with Conductor in 5 minutes. Step-by-step tutorial: discover MCP tools, call an LLM, execute tools, add human approval, and make it autonomous — all with durable execution guarantees."
|
|
---
|
|
|
|
# Build your first AI agent
|
|
|
|
**Build a durable AI agent in 5 minutes.** Your agent will discover tools, plan actions, execute them, and summarize results — with full crash recovery, observability, and human approval built in.
|
|
|
|
**Prerequisites:**
|
|
|
|
- Conductor running locally (`conductor server start`)
|
|
- An LLM provider API key (OpenAI or Anthropic)
|
|
- An MCP server running (we'll use a simple example below)
|
|
|
|
## Step 1: Start an MCP server
|
|
|
|
Your agent needs tools to call. MCP (Model Context Protocol) is the open standard for connecting AI agents to tools. Start a test MCP server — or use any MCP server you already have running.
|
|
|
|
```bash
|
|
pip install mcp-testkit
|
|
mcp-testkit --transport http
|
|
```
|
|
|
|
This starts an MCP server at `http://localhost:3001/mcp` with deterministic tools for testing. You'll use this URL in the workflow definition.
|
|
|
|
!!! tip "Any MCP server works"
|
|
Conductor connects to any MCP-compatible server. Use community MCP servers for GitHub, Slack, databases, or any API — or build your own. See the [MCP integration guide](mcp-guide.md) for details.
|
|
|
|
|
|
## Step 2: Configure your LLM provider
|
|
|
|
Set your API key as an environment variable before starting the server:
|
|
|
|
```bash
|
|
# Choose one (or both):
|
|
export OPENAI_API_KEY=sk-your-openai-key
|
|
export ANTHROPIC_API_KEY=sk-ant-your-anthropic-key
|
|
```
|
|
|
|
Then start (or restart) the server. Conductor auto-enables providers when their API key is set.
|
|
|
|
|
|
## Step 3: Create the agent workflow
|
|
|
|
Save this as `my_first_agent.json`. This is a complete AI agent in four tasks — no custom code, no workers, no framework:
|
|
|
|
```json
|
|
{
|
|
"name": "my_first_agent",
|
|
"description": "AI agent that discovers tools, plans, executes, and summarizes",
|
|
"version": 1,
|
|
"schemaVersion": 2,
|
|
"inputParameters": ["task"],
|
|
"tasks": [
|
|
{
|
|
"name": "discover_tools",
|
|
"taskReferenceName": "discover",
|
|
"type": "LIST_MCP_TOOLS",
|
|
"inputParameters": {
|
|
"mcpServer": "http://localhost:3001/mcp"
|
|
}
|
|
},
|
|
{
|
|
"name": "plan_action",
|
|
"taskReferenceName": "plan",
|
|
"type": "LLM_CHAT_COMPLETE",
|
|
"inputParameters": {
|
|
"llmProvider": "openai",
|
|
"model": "gpt-4o-mini",
|
|
"messages": [
|
|
{
|
|
"role": "system",
|
|
"message": "You are an AI agent. Available tools: ${discover.output.tools}. The user wants to: ${workflow.input.task}. Decide which tool to use. Respond with JSON: {\"method\": \"tool_name\", \"arguments\": {}}"
|
|
},
|
|
{
|
|
"role": "user",
|
|
"message": "${workflow.input.task}"
|
|
}
|
|
],
|
|
"temperature": 0.1,
|
|
"maxTokens": 500
|
|
}
|
|
},
|
|
{
|
|
"name": "execute_tool",
|
|
"taskReferenceName": "execute",
|
|
"type": "CALL_MCP_TOOL",
|
|
"inputParameters": {
|
|
"mcpServer": "http://localhost:3001/mcp",
|
|
"method": "${plan.output.result.method}",
|
|
"arguments": "${plan.output.result.arguments}"
|
|
}
|
|
},
|
|
{
|
|
"name": "summarize_result",
|
|
"taskReferenceName": "summarize",
|
|
"type": "LLM_CHAT_COMPLETE",
|
|
"inputParameters": {
|
|
"llmProvider": "openai",
|
|
"model": "gpt-4o-mini",
|
|
"messages": [
|
|
{
|
|
"role": "user",
|
|
"message": "The user asked: ${workflow.input.task}\n\nTool result: ${execute.output.content}\n\nSummarize this clearly for the user."
|
|
}
|
|
],
|
|
"maxTokens": 500
|
|
}
|
|
}
|
|
],
|
|
"outputParameters": {
|
|
"plan": "${plan.output.result}",
|
|
"toolResult": "${execute.output.content}",
|
|
"summary": "${summarize.output.result}"
|
|
}
|
|
}
|
|
```
|
|
|
|
**What each task does:**
|
|
|
|
| Task | Type | Purpose |
|
|
|------|------|---------|
|
|
| `discover` | `LIST_MCP_TOOLS` | Queries the MCP server to discover available tools |
|
|
| `plan` | `LLM_CHAT_COMPLETE` | Sends the tool list + user task to the LLM, which picks a tool and arguments |
|
|
| `execute` | `CALL_MCP_TOOL` | Calls the selected tool on the MCP server |
|
|
| `summarize` | `LLM_CHAT_COMPLETE` | Summarizes the raw tool output for the user |
|
|
|
|
Every task is a native Conductor system task. No workers to write, no code to deploy.
|
|
|
|
|
|
## Step 4: Register and run
|
|
|
|
```bash
|
|
# Register the workflow
|
|
conductor workflow create my_first_agent.json
|
|
|
|
# Run the agent synchronously — output prints directly to your terminal
|
|
curl -s -X POST 'http://localhost:8080/api/workflow/execute/my_first_agent/1' \
|
|
-H 'Content-Type: application/json' \
|
|
-d '{
|
|
"task": "What is the weather in San Francisco?"
|
|
}' | jq .
|
|
```
|
|
|
|
Or using the CLI:
|
|
|
|
```bash
|
|
conductor workflow start -w my_first_agent --sync --input '{"task": "What is the weather in San Francisco?"}'
|
|
```
|
|
|
|
Open [http://localhost:8080](http://localhost:8080) to see the execution. Click into the workflow to see each task's input, output, and timing.
|
|
|
|
!!! success "What just happened"
|
|
Your agent discovered tools from an MCP server, asked an LLM to pick the right one, executed it, and summarized the result. Every step was persisted — if the server had crashed at any point, execution would have resumed from the last completed task. No tokens wasted, no progress lost.
|
|
|
|
|
|
## Step 5: Add human approval
|
|
|
|
Real agents need guardrails. Add a `HUMAN` task between planning and execution so a person reviews the agent's plan before it acts.
|
|
|
|
Update `my_first_agent.json` — insert this task between `plan_action` and `execute_tool`:
|
|
|
|
```json
|
|
{
|
|
"name": "human_review",
|
|
"taskReferenceName": "approval",
|
|
"type": "HUMAN",
|
|
"inputParameters": {
|
|
"plannedAction": "${plan.output.result}",
|
|
"userTask": "${workflow.input.task}"
|
|
}
|
|
}
|
|
```
|
|
|
|
Now when you run the agent, it pauses after planning and waits for human approval. Approve it via the UI or API:
|
|
|
|
```bash
|
|
# Approve the plan (replace TASK_ID with the actual task ID from the execution)
|
|
curl -X POST 'http://localhost:8080/api/tasks' \
|
|
-H 'Content-Type: application/json' \
|
|
-d '{
|
|
"workflowInstanceId": "WORKFLOW_ID",
|
|
"taskId": "TASK_ID",
|
|
"status": "COMPLETED",
|
|
"outputData": {"approved": true, "reviewer": "you"}
|
|
}'
|
|
```
|
|
|
|
The approval is durable — the workflow stays paused indefinitely, even across server restarts and deploys, until someone approves it.
|
|
|
|
|
|
## Step 6: Make it autonomous
|
|
|
|
Turn your agent into an autonomous loop that keeps working until the task is done. Replace the linear workflow with a `DO_WHILE` loop:
|
|
|
|
```json
|
|
{
|
|
"name": "autonomous_agent",
|
|
"description": "Agent that loops until the task is complete",
|
|
"version": 1,
|
|
"schemaVersion": 2,
|
|
"inputParameters": ["task"],
|
|
"tasks": [
|
|
{
|
|
"name": "discover_tools",
|
|
"taskReferenceName": "discover",
|
|
"type": "LIST_MCP_TOOLS",
|
|
"inputParameters": {
|
|
"mcpServer": "http://localhost:3001/mcp"
|
|
}
|
|
},
|
|
{
|
|
"name": "agent_loop",
|
|
"taskReferenceName": "loop",
|
|
"type": "DO_WHILE",
|
|
"loopCondition": "if ($.loop['think'].output.result.done == true) { false; } else { true; }",
|
|
"loopOver": [
|
|
{
|
|
"name": "think",
|
|
"taskReferenceName": "think",
|
|
"type": "LLM_CHAT_COMPLETE",
|
|
"inputParameters": {
|
|
"llmProvider": "openai",
|
|
"model": "gpt-4o-mini",
|
|
"messages": [
|
|
{
|
|
"role": "system",
|
|
"message": "You are an autonomous agent. Available tools: ${discover.output.tools}. Previous results: ${loop.output.results}. Respond with JSON: {\"action\": \"tool_name\", \"arguments\": {}, \"done\": false} when you need to use a tool, or {\"answer\": \"final answer\", \"done\": true} when the task is complete."
|
|
},
|
|
{
|
|
"role": "user",
|
|
"message": "${workflow.input.task}"
|
|
}
|
|
],
|
|
"temperature": 0.1
|
|
}
|
|
},
|
|
{
|
|
"name": "act",
|
|
"taskReferenceName": "act",
|
|
"type": "SWITCH",
|
|
"evaluatorType": "javascript",
|
|
"expression": "$.think.output.result.done ? 'done' : 'call_tool'",
|
|
"decisionCases": {
|
|
"call_tool": [
|
|
{
|
|
"name": "execute_tool",
|
|
"taskReferenceName": "tool_call",
|
|
"type": "CALL_MCP_TOOL",
|
|
"inputParameters": {
|
|
"mcpServer": "http://localhost:3001/mcp",
|
|
"method": "${think.output.result.action}",
|
|
"arguments": "${think.output.result.arguments}"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"defaultCase": []
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"outputParameters": {
|
|
"answer": "${loop.output.think.output.result.answer}",
|
|
"iterations": "${loop.output.iteration}"
|
|
}
|
|
}
|
|
```
|
|
|
|
Each iteration of the loop is a durable checkpoint. If the agent crashes at iteration 12, it resumes from iteration 12 — not from the beginning. Every LLM call and tool call is persisted and observable.
|
|
|
|
|
|
## What you built
|
|
|
|
In 5 minutes, you built an AI agent that:
|
|
|
|
- **Discovers tools** from any MCP server at runtime
|
|
- **Plans actions** using an LLM
|
|
- **Executes tools** with full retry and error handling
|
|
- **Supports human approval** as a durable pause
|
|
- **Loops autonomously** until the task is complete
|
|
- **Survives crashes** without losing progress or re-running LLM calls
|
|
- **Is fully observable** — every prompt, response, tool call, and decision is recorded
|
|
|
|
All of this with zero custom code. The entire agent is a JSON workflow definition that Conductor executes with durable execution guarantees.
|
|
|
|
|
|
## Next steps
|
|
|
|
- **[MCP Integration](mcp-guide.md)** — Connect to any MCP server, expose workflows as MCP tools.
|
|
- **[Human-in-the-Loop](human-in-the-loop.md)** — Advanced approval patterns: conditional review, LLM-as-judge.
|
|
- **[Dynamic Workflows](dynamic-workflows.md)** — Agents that generate their own execution plans as JSON.
|
|
- **[Token Efficiency](token-efficiency.md)** — How durable execution saves tokens and reduces LLM costs.
|
|
- **[LLM Orchestration](llm-orchestration.md)** — 12 native LLM providers, vector databases, content generation.
|