When to embed Duvo vs. build the capability yourself
| Embed Duvo when… | Build natively when… |
|---|---|
| The task already exists as a configured Duvo Assignment | The task is simple and doesn’t need connections or HITL |
| The task involves approvals, sensitive systems, or audit needs | Latency is critical and a Job round-trip isn’t acceptable |
| Non-developers need to maintain the task’s SOP | You want full control over the execution environment |
| The task spans multiple Connections (Gmail + Sheets + Slack…) | The task has no human-in-the-loop requirement |
- An editor-agent reviews a document and delegates any compliance action to a Duvo Assignment.
- A customer copilot triages a request and hands a regulated branch (refund, escalation) to Duvo, where a human can approve it.
- An internal AI workbench catalogs Duvo Assignments as named skills and routes work to them by category.
How it works
Your agent connects to the Duvo MCP server (https://api.duvo.ai/v2/mcp). Every Duvo Public API endpoint is auto-exposed as an MCP tool. Your agent calls those tools to start Jobs, poll for completion, respond to human-in-the-loop requests, and collect results — all through a standard MCP interface.
Scoping which Assignments your agent can call
The Duvo MCP server exposes tools for the full Public API. Your agent can calllistAgents to discover all Assignments visible to its API key, then filter by name or ID to invoke specific ones.
Narrowing scope with API keys:
Each API key is scoped to a team and inherits the permissions of the user who created it. To limit a parent agent to a subset of Assignments, create a dedicated Duvo user with access only to the relevant Assignments and generate an API key for that user. This prevents the parent agent from accidentally discovering or starting Assignments it shouldn’t touch.
Discovering Assignments at startup:
How an Assignment appears as a tool
When your agent callslistAgents, each Assignment is returned with metadata your agent can use to decide which one to invoke. Here is a trimmed example of the response (additional fields omitted for brevity):
id, name, and latest_build.revision_description. The name and description come from what was entered in the Duvo dashboard — edit them there to make the Assignment self-describing for your agent.
Tips for writing agent-friendly Assignment metadata:
- Name: use a verb phrase — “Process Refund Request”, “Triage Support Ticket”, “Update Inventory Record”.
- Revision description (
latest_build.revision_description): explain the input the Assignment expects and the output it produces — “Takes a customer complaint email body. Returns a triage decision (escalate / auto-resolve / needs-more-info) with a one-sentence rationale.”
Invocation patterns
All Job endpoints are on the base URLhttps://api.duvo.ai/v2. Starting a Job is team-scoped (POST /teams/{team_id}/runs); reading and responding to a Job is addressed by run_id.
Synchronous (poll until done)
Start a Job, then pollgetRun until the status is completed, failed, or stopped. Suitable for short-running Assignments (under a few minutes).
Asynchronous with a webhook
Provide awebhook_url when starting the Job. Duvo POSTs to that URL on state changes (run_completed, run_failed, run_interrupted) and when the Assignment needs input (human_request), so your agent doesn’t have to poll. Filter on the payload’s event field for the case you care about.
HITL handoff
When Duvo reaches a step that requires human approval, the Job’s status changes towaiting. If your parent agent is polling, it detects this status and can either:
- Forward the request to a human — surface the
titleanddescriptionfromgetRun’spending_human_requestfield in your agent’s own UI or chat thread, then relay the human’s answer back viarespondToHumanRequest. - Respond programmatically — if your agent has enough context to make the decision itself, it can call
respondToHumanRequestdirectly without surfacing it to a human.
Trust and guardrails
What the parent agent can’t do:- The parent agent operates under the permissions of its API key. It cannot bypass Connection-level authorization — if the Assignment uses a Gmail Connection that the API key’s user can’t access, the Job will fail with a permissions error.
- The parent agent cannot modify the Assignment’s SOP or Connections through an MCP tool call without the corresponding write endpoints, which should be locked down for service accounts.
End-to-end example: email triage with a human approval gate
A parent agent monitors an inbound email queue. When it receives a complaint that touches a financial policy, it delegates to a Duvo Assignment, waits for a human to approve the proposed response, then sends the final email.- The parent agent starts a Job on the “Complaint Triage” Assignment with the raw email body.
- Duvo’s Assignment reads the complaint, connects to the order system via its configured Connection, drafts a refund proposal, and pauses — asking an operator to approve before sending.
- The parent agent detects
waiting, fetches the HITL request, and surfaces the draft to an on-call operator (via a chat message, Slack notification, or UI). - The operator approves or rejects. The parent agent relays that decision back to Duvo.
- Duvo sends the approved response and marks the Job
completed. - The parent agent reads the final result and continues its own workflow.
Related
- The Duvo MCP server — how to configure authentication and connect any MCP-compatible host
- Connect a custom MCP to Duvo — the inverse direction: bring your own tools into Duvo Assignments
- Running Assignments via API — full API reference for Jobs, messages, and HITL responses
- Guardrails for High-Risk Automations — risk framework for delegating irreversible actions
- Audit Log and Activity Tracking — how to trace which agent started which Job