Use case
Agents that ask people
An agent reaches a question only a person can answer. It calls escalate_and_wait like any other tool, a person answers in the dashboard, and the agent continues with the answer.
Surfaces: MCP · Dashboard
The moment
An agent is three steps into a job: download this week’s invoices from a supplier portal, match them against purchase orders, flag the mismatches. On step three the portal asks for a login. The stored connection was rotated last night.
The agent has options, and most of them are bad. It can give up and lose its progress. It can retry until it burns its budget. It can write “please provide credentials” into a log nobody reads.
What it needs is a person, for about thirty seconds, with a form that asks for exactly one thing. Then it needs to carry on from step three.
Two directions, one row
People and agents meet at the escalation row, from both sides:
| Direction | Who starts | Who answers | Where |
|---|---|---|---|
| An agent asks a person | An agent running inside Long Tail | A member of the target role | Dashboard |
| A person sends their agent | Claude Code, Claude Desktop, Cursor, any MCP client | The agent, acting with that person’s roles | The /mcp endpoint |
Both directions use the same row, the same role checks and the same audit trail.
An agent that asks a person
Long Tail exposes its escalation queue as an MCP server, long-tail-human-queue. To an agent, a person is a tool. When an agent loop inside Long Tail needs input before it can continue, it calls escalate_and_wait with a form describing what it needs:
{ "role": "engineer", "message": "The supplier portal rejected the stored login. I need a current username and password to download this week's invoices.", "form_schema": { "type": "object", "required": ["username", "password"], "properties": { "username": { "type": "string" }, "password": { "type": "string", "format": "password" } } }, "data": { "portal": "https://suppliers.acme.dev", "step": "download invoice batch 3 of 4" }}The call creates an escalation in the engineer queue and returns a signal id. The workflow parks on that signal. It does not poll, and it spends nothing while it waits. The next step in the run is the one that receives the person’s answer.
On the dashboard, an engineer sees the agent’s message, its context and a two-field form. They type the login and submit. Fields marked format: "password" are replaced with ephemeral credential tokens (eph:v1:...) before the payload reaches the agent. The agent passes the token into its next tool call exactly as received, and the raw secret never enters the agent’s context or its history.
The run continues from step three with the invoices it had already downloaded.
| Tool | What it does |
|---|---|
escalate_and_wait |
Create an escalation and pause the workflow until a person responds |
escalate_to_human |
Create an escalation and continue. Use it for notices that need no answer |
check_resolution |
Read an escalation’s status and its resolver payload |
get_available_work |
List the pending, unclaimed escalations for a role |
claim_and_resolve |
Claim an escalation and resolve it in one call |
Route the question to one person
Sometimes the right person is a specific person. Set assigned_to on escalate_and_wait and the item is pre-claimed for that user. Give them a membership in the role with read_self and write_self, and they see exactly that one item and nothing else in the queue. A contractor can approve one purchase order without seeing the rest of finance’s work.
Flag it back to an agent
The handoff also runs the other way. A reviewer looks at a failed extraction and sees the cause at once: page one was scanned upside down. They know what is wrong, but they cannot produce the data by hand. They resolve with a triage flag instead of an answer:
{ "resolverPayload": { "_lt": { "needsTriage": true, "hint": "image_orientation" }, "notes": "Page 1 is upside down" }}With the MCP escalation strategy turned on (escalation: { strategy: 'mcp' } in start()), that resolution routes to the triage workflow. It reads what happened upstream, calls the tools the hint points to, and re-runs the original step with corrected input. The parent workflow resumes as if the step had succeeded the first time. The triage workflows register when an ANTHROPIC_API_KEY or OPENAI_API_KEY is set.
Your agent, acting as you
It is 7 a.m. and a shift lead opens Claude Code before the stand-up. Connecting takes one command:
claude mcp add --transport http long-tail https://lt.acme.dev/mcpThey run /mcp, pick Authenticate, and sign in once in the browser. The consent page offers two choices:
| Choice | The client may |
|---|---|
| Allow read-only | Read what you can read, and run workflows marked read-safe |
| Allow as me | Do anything you can do: claim, resolve, invoke and administer wherever your roles allow |
Then the work is a conversation:
- “How many escalations are pending, by role?”
- “Find the escalation where
orderIdis A-1042 and show me its status.” - “Claim it and resolve it as approved, with a note that the supplier confirmed by phone.”
Behind those sentences are ordinary tool calls: get_escalation_stats, find_by_metadata, claim_escalation, admin_resolve_escalation. Each one runs as the shift lead. Every result is limited to their roles, and every action is recorded under their name. An account that holds only the reviewer role can resolve reviewer escalations and nothing else, however the prompt is phrased.
Access tokens last five minutes and refresh silently. Every request reads the grant again, so a role removed this morning is gone from the agent’s next call. Disconnect a client under Connected apps in the user menu.
Agents that run unattended
A nightly agent has no browser to sign in with. Give it a service account instead: create one under Accounts → Service Accounts, assign the roles it acts under, and generate a key scoped mcp:read or mcp:full. Point the client at it with the key kept in the environment:
{ "mcpServers": { "longtail-prod": { "type": "http", "url": "https://lt.acme.dev/mcp", "headers": { "Authorization": "Bearer ${LONGTAIL_PROD_KEY}" } } }}Give production a read key by default, and use a full key only when the agent is meant to change something there.
What the workflow does with the answer
Whoever answers, the answer lands in one place. When a person resolves the agent’s question, the waiting run resumes with the payload. When an agent resolves a person’s escalation, the workflow that raised it resumes with the agent’s payload. On a role that enforces its form, that payload passes the same validation a person’s submission does, and claim_and_resolve validates before it claims, so a rejected payload never leaves a claim stranded.
The row records who asked, who answered, what was decided and when. The next time the same question comes up, that record is the worked example.