MailSlurp logo

Build an agent worker with human review

Documentation navigation
Search documentation

Process scoped conversations using claims, guarded drafts, idempotent replies and durable events.

View MarkdownAgent setup

Use a scoped agent connection for a background worker that handles conversations. Create the connection first and grant only the inboxes and permissions the worker needs. Use MCP for an interactive AI client; use the Agent REST API when your application owns the worker loop.

Discover capabilities at startup

Call GET /agent/capabilities with the scoped agent key. The response describes permissions, resource scope, feature availability and server limits. Check it before accepting work rather than assuming every connection with the same role has identical access. Report a worker heartbeat at startup and periodically while it can accept work.

GET /agent/capabilities

Discover this agent connection's capabilities

Returns the connection identity, role, effective permission names, declared resource scope, feature availability, and server-enforced limits. Call this once during worker startup instead of hard-coding role behavior.

Request, parameters, and responses

Responses

StatusSchemaDescription
200AgentCapabilitiesDtoOK
HTTP and SDK snippets

HTTP

HTTP
GET /agent/capabilities HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json

cURL

cURL
curl -X GET "https://api.mailslurp.com/agent/capabilities" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json"

JavaScript SDK

JavaScript SDK
import { Configuration, AgentControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const agentController = new AgentControllerApi(config);

const result = await agentController.agentGetCapabilities();

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.agent_controller_api import AgentControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    agentController = AgentControllerApi(api_client)
    result = agentController.agent_get_capabilities()
POST /agent/runtime/heartbeat

Report a worker heartbeat

Records one running worker instance and its deployed release for owner-side health monitoring. Send this during startup and periodically while the process can accept work; it does not claim or mutate a conversation.

Request, parameters, and responses

Request body (required)

AgentWorkerHeartbeatOptions application/json
FieldTypeRequiredDescription
workerIdstringYes
instanceIdstringYes
releasestringNo
Request example
{
  "workerId": "00000000-0000-4000-8000-000000000000",
  "instanceId": "00000000-0000-4000-8000-000000000000",
  "release": "value"
}

Responses

StatusSchemaDescription
200AgentWorkerHeartbeatDtoOK
HTTP and SDK snippets

HTTP

HTTP
POST /agent/runtime/heartbeat HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json
Content-Type: application/json

{
  "workerId": "00000000-0000-4000-8000-000000000000",
  "instanceId": "00000000-0000-4000-8000-000000000000",
  "release": "value"
}

cURL

cURL
curl -X POST "https://api.mailslurp.com/agent/runtime/heartbeat" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  --data '{"workerId":"00000000-0000-4000-8000-000000000000","instanceId":"00000000-0000-4000-8000-000000000000","release":"value"}'

JavaScript SDK

JavaScript SDK
import { Configuration, AgentControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const agentController = new AgentControllerApi(config);
const request = {
  "agentWorkerHeartbeatOptions": {
    "workerId": "00000000-0000-4000-8000-000000000000",
    "instanceId": "00000000-0000-4000-8000-000000000000",
    "release": "value"
  }
};

const result = await agentController.agentReportWorkerHeartbeat(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.agent_controller_api import AgentControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    agentController = AgentControllerApi(api_client)
    agent_worker_heartbeat_options = {
      "workerId": "00000000-0000-4000-8000-000000000000",
      "instanceId": "00000000-0000-4000-8000-000000000000",
      "release": "value"
    }
    result = agentController.agent_report_worker_heartbeat(agent_worker_heartbeat_options)

Claim one conversation

POST /agent/work-items/next atomically selects and claims an available conversation. Give each worker a distinct workerId and a lease duration within the advertised limits. An empty work item means no conversation was selected: back off instead of calling continuously.

{ "workerId": "support-worker-1", "leaseSeconds": 60 }
POST /agent/work-items/next

Claim the next conversation work item

Selects the oldest available scoped conversation and atomically claims it for one worker. This combines queue selection and claim acquisition so concurrent workers do not need to coordinate those steps themselves.

Request, parameters, and responses

Request body (required)

GetNextAgentWorkItemOptions application/json
FieldTypeRequiredDescription
workerIdstringYes
leaseSecondsinteger:int32Yes
cursorstringNo
inboxIdstring:uuidNo
hasAttachmentsbooleanNo
Request example
{
  "workerId": "00000000-0000-4000-8000-000000000000",
  "leaseSeconds": 1,
  "cursor": "value",
  "inboxId": "00000000-0000-4000-8000-000000000000",
  "hasAttachments": true
}

Responses

StatusSchemaDescription
200AgentWorkItemDtoThe claimed conversation, or an empty work item when none is available.
defaultAgentApiErrorDtoAgent API error with a stable code, retry guidance, support-safe request ID, and bounded details.
HTTP and SDK snippets

HTTP

HTTP
POST /agent/work-items/next HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json
Content-Type: application/json

{
  "workerId": "00000000-0000-4000-8000-000000000000",
  "leaseSeconds": 1,
  "cursor": "value",
  "inboxId": "00000000-0000-4000-8000-000000000000",
  "hasAttachments": true
}

cURL

cURL
curl -X POST "https://api.mailslurp.com/agent/work-items/next" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  --data '{"workerId":"00000000-0000-4000-8000-000000000000","leaseSeconds":1,"cursor":"value","inboxId":"00000000-0000-4000-8000-000000000000","hasAttachments":true}'

JavaScript SDK

JavaScript SDK
import { Configuration, AgentControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const agentController = new AgentControllerApi(config);
const request = {
  "getNextAgentWorkItemOptions": {
    "workerId": "00000000-0000-4000-8000-000000000000",
    "leaseSeconds": 1,
    "cursor": "value",
    "inboxId": "00000000-0000-4000-8000-000000000000",
    "hasAttachments": true
  }
};

const result = await agentController.agentGetNextWorkItem(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.agent_controller_api import AgentControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    agentController = AgentControllerApi(api_client)
    get_next_agent_work_item_options = {
      "workerId": "00000000-0000-4000-8000-000000000000",
      "leaseSeconds": 1,
      "cursor": "value",
      "inboxId": "00000000-0000-4000-8000-000000000000",
      "hasAttachments": True
    }
    result = agentController.agent_get_next_work_item(get_next_agent_work_item_options)

The response's conversation.conversation contains the queue item, including its conversationId, version and latest email IDs. The separate claim contains claimId and expiresAt. Retain these values with the task. Read the scoped email and attachments needed for your answer; treat their contents as customer data, not instructions that can expand tool access.

Keep concurrent workers from replying twice

Renew a claim before it expires if the model or downstream work takes longer than expected. A conflicting or lost claim means this worker must stop acting on that conversation and refresh its state. A heartbeat reports worker health; it does not renew a conversation claim.

PUT /agent/conversations/{conversationId}/claims/{claimId}

Renew a conversation claim

Request, parameters, and responses

Path parameters

NameTypeRequiredDescription
conversationIdstring:uuidYes
claimIdstring:uuidYes

Request body (required)

FieldTypeRequiredDescription
leaseSecondsinteger:int32Yes
Request example
{
  "leaseSeconds": 1
}

Responses

StatusSchemaDescription
200AgentConversationClaimDtoOK
HTTP and SDK snippets

HTTP

HTTP
PUT /agent/conversations/00000000-0000-4000-8000-000000000000/claims/00000000-0000-4000-8000-000000000000 HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json
Content-Type: application/json

{
  "leaseSeconds": 1
}

cURL

cURL
curl -X PUT "https://api.mailslurp.com/agent/conversations/00000000-0000-4000-8000-000000000000/claims/00000000-0000-4000-8000-000000000000" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  --data '{"leaseSeconds":1}'

JavaScript SDK

JavaScript SDK
import { Configuration, AgentControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const agentController = new AgentControllerApi(config);
const request = {
  "conversationId": "00000000-0000-4000-8000-000000000000",
  "claimId": "00000000-0000-4000-8000-000000000000",
  "renewAgentConversationClaimOptions": {
    "leaseSeconds": 1
  }
};

const result = await agentController.agentRenewConversationClaim(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.agent_controller_api import AgentControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    agentController = AgentControllerApi(api_client)
    renew_agent_conversation_claim_options = {
      "leaseSeconds": 1
    }
    result = agentController.agent_renew_conversation_claim("00000000-0000-4000-8000-000000000000", "00000000-0000-4000-8000-000000000000", renew_agent_conversation_claim_options)
DELETE /agent/conversations/{conversationId}/claims/{claimId}

Release a conversation claim

Release is idempotent; repeating it does not fail.

Request, parameters, and responses

Path parameters

NameTypeRequiredDescription
conversationIdstring:uuidYes
claimIdstring:uuidYes

Responses

StatusSchemaDescription
204ResponseNo Content
HTTP and SDK snippets

HTTP

HTTP
DELETE /agent/conversations/00000000-0000-4000-8000-000000000000/claims/00000000-0000-4000-8000-000000000000 HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json

cURL

cURL
curl -X DELETE "https://api.mailslurp.com/agent/conversations/00000000-0000-4000-8000-000000000000/claims/00000000-0000-4000-8000-000000000000" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json"

JavaScript SDK

JavaScript SDK
import { Configuration, AgentControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const agentController = new AgentControllerApi(config);
const request = {
  "conversationId": "00000000-0000-4000-8000-000000000000",
  "claimId": "00000000-0000-4000-8000-000000000000"
};

const result = await agentController.agentReleaseConversationClaim(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.agent_controller_api import AgentControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    agentController = AgentControllerApi(api_client)
    result = agentController.agent_release_conversation_claim("00000000-0000-4000-8000-000000000000", "00000000-0000-4000-8000-000000000000")

Pass expectedConversationVersion and expectedLatestEmailId when preparing or completing work. These guards catch a new inbound message or other change after the worker selected its context. On a freshness conflict, read the updated conversation and reconsider the reply; do not resend the stale answer blindly.

Prepare a draft or request human review

Use agentPrepareWorkItemReply to create a threaded draft from sourceEmailId, a reply body and the saved guards. Preparing a draft does not send it. When a person needs to decide, defer the work with a reason, priority, claim ID and optional draft ID. Deferral creates a durable review handoff and releases the supplied claim after it succeeds.

POST /agent/work-items/{conversationId}/prepare-reply

Prepare a guarded reply draft

Checks that the selected conversation and latest inbound email are still current, then creates a correctly threaded reply draft. An optional internal note records context for human review without sending email.

Request, parameters, and responses

Path parameters

NameTypeRequiredDescription
conversationIdstring:uuidYes

Request body (required)

PrepareAgentReplyOptions application/json
FieldTypeRequiredDescription
sourceEmailIdstring:uuidYes
replyReplyToEmailOptionsYes
expectedConversationVersioninteger:int64No
expectedLatestEmailIdstring:uuidNo
internalNotestringNo
claimIdstring:uuidNo
Request example
{
  "sourceEmailId": "00000000-0000-4000-8000-000000000000",
  "reply": {
    "body": "Hello from MailSlurp",
    "isHTML": true,
    "from": "user@example.com",
    "replyTo": "user@example.com",
    "customHeaders": {
      "example": "value"
    },
    "charset": "value"
  },
  "expectedConversationVersion": 1,
  "expectedLatestEmailId": "00000000-0000-4000-8000-000000000000",
  "internalNote": "value",
  "claimId": "00000000-0000-4000-8000-000000000000"
}

Responses

StatusSchemaDescription
200AgentPreparedReplyDtoThe created reply draft and refreshed conversation state.
defaultAgentApiErrorDtoAgent API error with a stable code, retry guidance, support-safe request ID, and bounded details.
HTTP and SDK snippets

HTTP

HTTP
POST /agent/work-items/00000000-0000-4000-8000-000000000000/prepare-reply HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json
Content-Type: application/json

{
  "sourceEmailId": "00000000-0000-4000-8000-000000000000",
  "reply": {
    "body": "Hello from MailSlurp",
    "isHTML": true,
    "from": "user@example.com",
    "replyTo": "user@example.com",
    "customHeaders": {
      "example": "value"
    },
    "charset": "value"
  },
  "expectedConversationVersion": 1,
  "expectedLatestEmailId": "00000000-0000-4000-8000-000000000000",
  "internalNote": "value",
  "claimId": "00000000-0000-4000-8000-000000000000"
}

cURL

cURL
curl -X POST "https://api.mailslurp.com/agent/work-items/00000000-0000-4000-8000-000000000000/prepare-reply" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  --data '{"sourceEmailId":"00000000-0000-4000-8000-000000000000","reply":{"body":"Hello from MailSlurp","isHTML":true,"from":"user@example.com","replyTo":"user@example.com","customHeaders":{"example":"value"},"charset":"value"},"expectedConversationVersion":1,"expectedLatestEmailId":"00000000-0000-4000-8000-000000000000","internalNote":"value","claimId":"00000000-0000-4000-8000-000000000000"}'

JavaScript SDK

JavaScript SDK
import { Configuration, AgentControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const agentController = new AgentControllerApi(config);
const request = {
  "conversationId": "00000000-0000-4000-8000-000000000000",
  "prepareAgentReplyOptions": {
    "sourceEmailId": "00000000-0000-4000-8000-000000000000",
    "reply": {
      "body": "Hello from MailSlurp",
      "isHTML": true,
      "from": "user@example.com",
      "replyTo": "user@example.com",
      "customHeaders": {
        "example": "value"
      },
      "charset": "value"
    },
    "expectedConversationVersion": 1,
    "expectedLatestEmailId": "00000000-0000-4000-8000-000000000000",
    "internalNote": "value",
    "claimId": "00000000-0000-4000-8000-000000000000"
  }
};

const result = await agentController.agentPrepareWorkItemReply(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.agent_controller_api import AgentControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    agentController = AgentControllerApi(api_client)
    prepare_agent_reply_options = {
      "sourceEmailId": "00000000-0000-4000-8000-000000000000",
      "reply": {
        "body": "Hello from MailSlurp",
        "isHTML": True,
        "from": "user@example.com",
        "replyTo": "user@example.com",
        "customHeaders": {
          "example": "value"
        },
        "charset": "value"
      },
      "expectedConversationVersion": 1,
      "expectedLatestEmailId": "00000000-0000-4000-8000-000000000000",
      "internalNote": "value",
      "claimId": "00000000-0000-4000-8000-000000000000"
    }
    result = agentController.agent_prepare_work_item_reply("00000000-0000-4000-8000-000000000000", prepare_agent_reply_options)
POST /agent/work-items/{conversationId}/defer

Defer a work item to human review

Creates or returns the active review handoff and releases the supplied claim after the handoff is durable. Deferral is a normal workflow result rather than an operational failure.

Request, parameters, and responses

Path parameters

NameTypeRequiredDescription
conversationIdstring:uuidYes

Request body (required)

DeferAgentWorkItemOptions application/json
FieldTypeRequiredDescription
reasonCodestringYes
reasonstringNo
priorityenum: LOW | NORMAL | HIGH | URGENTYes
sourceEmailIdstring:uuidNo
draftIdstring:uuidNo
expectedConversationVersioninteger:int64No
claimIdstring:uuidNo
Request example
{
  "reasonCode": "value",
  "priority": "LOW",
  "reason": "value",
  "sourceEmailId": "00000000-0000-4000-8000-000000000000",
  "draftId": "00000000-0000-4000-8000-000000000000",
  "expectedConversationVersion": 1
}

Responses

StatusSchemaDescription
200AgentDeferredWorkItemDtoThe human-review handoff and refreshed conversation state.
defaultAgentApiErrorDtoAgent API error with a stable code, retry guidance, support-safe request ID, and bounded details.
HTTP and SDK snippets

HTTP

HTTP
POST /agent/work-items/00000000-0000-4000-8000-000000000000/defer HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json
Content-Type: application/json

{
  "reasonCode": "value",
  "priority": "LOW",
  "reason": "value",
  "sourceEmailId": "00000000-0000-4000-8000-000000000000",
  "draftId": "00000000-0000-4000-8000-000000000000",
  "expectedConversationVersion": 1
}

cURL

cURL
curl -X POST "https://api.mailslurp.com/agent/work-items/00000000-0000-4000-8000-000000000000/defer" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  --data '{"reasonCode":"value","priority":"LOW","reason":"value","sourceEmailId":"00000000-0000-4000-8000-000000000000","draftId":"00000000-0000-4000-8000-000000000000","expectedConversationVersion":1}'

JavaScript SDK

JavaScript SDK
import { Configuration, AgentControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const agentController = new AgentControllerApi(config);
const request = {
  "conversationId": "00000000-0000-4000-8000-000000000000",
  "deferAgentWorkItemOptions": {
    "reasonCode": "value",
    "priority": "LOW",
    "reason": "value",
    "sourceEmailId": "00000000-0000-4000-8000-000000000000",
    "draftId": "00000000-0000-4000-8000-000000000000",
    "expectedConversationVersion": 1
  }
};

const result = await agentController.agentDeferWorkItem(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.agent_controller_api import AgentControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    agentController = AgentControllerApi(api_client)
    defer_agent_work_item_options = {
      "reasonCode": "value",
      "priority": "LOW",
      "reason": "value",
      "sourceEmailId": "00000000-0000-4000-8000-000000000000",
      "draftId": "00000000-0000-4000-8000-000000000000",
      "expectedConversationVersion": 1
    }
    result = agentController.agent_defer_work_item("00000000-0000-4000-8000-000000000000", defer_agent_work_item_options)

Examples of review reasons include an ambiguous request, a requested refund or missing order information. Add internal notes for the reviewer rather than putting operational context into the customer's email. Open the agent's Review queue to inspect the conversation and draft before sending.

Complete an approved autonomous reply

agentCompleteWorkItem rechecks freshness, sends a threaded reply with an idempotencyKey, and releases the supplied claim only after sending succeeds. Store one key for the logical reply before making the request. Retry an interrupted request with that same key and unchanged payload; a different reply needs a different key.

POST /agent/work-items/{conversationId}/complete

Complete a work item with an idempotent reply

Revalidates conversation freshness, sends one threaded reply with an idempotency key, and releases the supplied claim only after the send succeeds.

Request, parameters, and responses

Path parameters

NameTypeRequiredDescription
conversationIdstring:uuidYes

Request body (required)

CompleteAgentWorkItemOptions application/json
FieldTypeRequiredDescription
sourceEmailIdstring:uuidYes
replyReplyToEmailOptionsYes
idempotencyKeystringYes
expectedConversationVersioninteger:int64No
expectedLatestEmailIdstring:uuidNo
claimIdstring:uuidNo
Request example
{
  "sourceEmailId": "00000000-0000-4000-8000-000000000000",
  "reply": {
    "body": "Hello from MailSlurp",
    "isHTML": true,
    "from": "user@example.com",
    "replyTo": "user@example.com",
    "customHeaders": {
      "example": "value"
    },
    "charset": "value"
  },
  "idempotencyKey": "value",
  "expectedConversationVersion": 1,
  "expectedLatestEmailId": "00000000-0000-4000-8000-000000000000",
  "claimId": "00000000-0000-4000-8000-000000000000"
}

Responses

StatusSchemaDescription
200AgentCompletedWorkItemDtoThe durable sent-email result and claim release state.
defaultAgentApiErrorDtoAgent API error with a stable code, retry guidance, support-safe request ID, and bounded details.
HTTP and SDK snippets

HTTP

HTTP
POST /agent/work-items/00000000-0000-4000-8000-000000000000/complete HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json
Content-Type: application/json

{
  "sourceEmailId": "00000000-0000-4000-8000-000000000000",
  "reply": {
    "body": "Hello from MailSlurp",
    "isHTML": true,
    "from": "user@example.com",
    "replyTo": "user@example.com",
    "customHeaders": {
      "example": "value"
    },
    "charset": "value"
  },
  "idempotencyKey": "value",
  "expectedConversationVersion": 1,
  "expectedLatestEmailId": "00000000-0000-4000-8000-000000000000",
  "claimId": "00000000-0000-4000-8000-000000000000"
}

cURL

cURL
curl -X POST "https://api.mailslurp.com/agent/work-items/00000000-0000-4000-8000-000000000000/complete" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  --data '{"sourceEmailId":"00000000-0000-4000-8000-000000000000","reply":{"body":"Hello from MailSlurp","isHTML":true,"from":"user@example.com","replyTo":"user@example.com","customHeaders":{"example":"value"},"charset":"value"},"idempotencyKey":"value","expectedConversationVersion":1,"expectedLatestEmailId":"00000000-0000-4000-8000-000000000000","claimId":"00000000-0000-4000-8000-000000000000"}'

JavaScript SDK

JavaScript SDK
import { Configuration, AgentControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const agentController = new AgentControllerApi(config);
const request = {
  "conversationId": "00000000-0000-4000-8000-000000000000",
  "completeAgentWorkItemOptions": {
    "sourceEmailId": "00000000-0000-4000-8000-000000000000",
    "reply": {
      "body": "Hello from MailSlurp",
      "isHTML": true,
      "from": "user@example.com",
      "replyTo": "user@example.com",
      "customHeaders": {
        "example": "value"
      },
      "charset": "value"
    },
    "idempotencyKey": "value",
    "expectedConversationVersion": 1,
    "expectedLatestEmailId": "00000000-0000-4000-8000-000000000000",
    "claimId": "00000000-0000-4000-8000-000000000000"
  }
};

const result = await agentController.agentCompleteWorkItem(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.agent_controller_api import AgentControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    agentController = AgentControllerApi(api_client)
    complete_agent_work_item_options = {
      "sourceEmailId": "00000000-0000-4000-8000-000000000000",
      "reply": {
        "body": "Hello from MailSlurp",
        "isHTML": True,
        "from": "user@example.com",
        "replyTo": "user@example.com",
        "customHeaders": {
          "example": "value"
        },
        "charset": "value"
      },
      "idempotencyKey": "value",
      "expectedConversationVersion": 1,
      "expectedLatestEmailId": "00000000-0000-4000-8000-000000000000",
      "claimId": "00000000-0000-4000-8000-000000000000"
    }
    result = agentController.agent_complete_work_item("00000000-0000-4000-8000-000000000000", complete_agent_work_item_options)

Record conversation, claim and request identifiers for debugging. Use the returned error code and retry guidance to separate permission problems, stale work and transient failures. Do not report success just because the model produced text.

Use durable events for event-driven workers

GET /agent/events supports bounded long polling with waitSeconds. Events are delivered at least once. Deduplicate by eventId and persist nextCursor only after the page has been durably processed. After a restart, resume from the saved cursor.

GET /agent/events

Read durable scoped automation events

Returns an ordered at-least-once event batch. Persist nextCursor after processing and deduplicate by eventId. waitSeconds enables bounded long polling; production workers should not continuously call latest-email polling.

Request, parameters, and responses

Query parameters

NameTypeRequiredDescription
cursorstringNo
eventTypeenum: EMAIL_RECEIVED | EMAIL_SENT | SMS_RECEIVED | SMS_SENT | CONVERSATION_CLAIMED | CONVERSATION_CLAIM_RELEASED[]No
sizeinteger:int32No
waitSecondsinteger:int32No

Responses

StatusSchemaDescription
200AgentAutomationEventPageDtoOK
HTTP and SDK snippets

HTTP

HTTP
GET /agent/events?cursor=value&eventType=value&size=value HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json

cURL

cURL
curl -X GET "https://api.mailslurp.com/agent/events?cursor=value&eventType=value&size=value" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json"

JavaScript SDK

JavaScript SDK
import { Configuration, AgentControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const agentController = new AgentControllerApi(config);
const request = {
  "cursor": "value",
  "eventType": [
    "value"
  ],
  "size": null
};

const result = await agentController.agentListAutomationEvents(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.agent_controller_api import AgentControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    agentController = AgentControllerApi(api_client)
    result = agentController.agent_list_automation_events(cursor="value", event_type=["value"], size=NaN)

An event identifies work to inspect; claims coordinate who acts on it. If your application already receives MailSlurp webhooks, use the reliable receiver pattern and keep the scoped key in the worker. Use scoped SMS and TOTP for those channels rather than treating an email work item as an SMS conversation.