Skip to content

Integrating Hosted Research Agents into Applications

Calling a language model usually looks synchronous: send a prompt, wait for a response, and display the text. A hosted research agent such as Manus has a different execution model. It may browse the web, use connectors, work with files, run tools in a sandbox, pause for clarification, and produce several artifacts over minutes rather than seconds.

That difference changes the application architecture. The integration is no longer only an API request. It is a long-running job whose identity, state, inputs, approvals, outputs, and failures must be preserved.

This page uses Manus as the concrete example because the source workshop demonstrates a Manus-to-Slack integration. The patterns also apply to other hosted agent APIs.

Version note: Manus changes quickly. The API details on this page were checked against the official API v2 documentation on July 22, 2026. API v1, used by older examples, is deprecated. Verify version-sensitive fields, limits, agent profiles, and event types before implementing them.

A normal model call asks a model to generate the next response. A hosted agent task delegates a goal to an execution system.

Direct model callHosted agent task
Usually one request and one responseAsynchronous task with several events
Your code explicitly calls every toolThe agent can select and sequence available tools
Usually completes in secondsMay run for minutes or longer
Returns text or a structured responseMay return messages, files, links, and structured data
Your process owns the complete loopThe provider runs part of the loop in its own environment
Missing information usually produces a best-effort answerThe task may stop and ask a question

The useful abstraction is therefore:

Create task -> persist task ID -> observe events -> supply input if needed -> deliver result

Do not keep the original HTTP request open while the agent works. Return a local job ID or acknowledgement to the caller, then continue the task asynchronously.

Manus describes its product as a general-purpose autonomous agent with access to a cloud execution environment. Through its web product and API, a task can use files, web browsing, connectors, skills, and other tools while working toward an outcome.

That makes Manus closer to a managed agent runtime than a raw inference endpoint:

flowchart LR
    U["User goal"] --> M["Manus task"]
    M --> P["Plan and choose actions"]
    P --> B["Browse or search"]
    P --> F["Read and create files"]
    P --> C["Use approved connectors"]
    P --> S["Run skills or tools"]
    B --> R["Research result"]
    F --> R
    C --> R
    S --> R

The application does not need to implement every research step. It still owns everything around the delegated task:

  • authenticating the user
  • deciding what context and permissions may be sent
  • recording the relationship between the user request and the Manus task
  • presenting clarification and approval requests to the correct person
  • verifying callbacks
  • enforcing application-specific policy
  • storing and delivering the final result
  • handling cancellation, retries, and audit records

Manus can persist progress inside its task runtime. That does not make the rest of your application durable automatically.

The workshop remains useful for its architectural ideas, but its product details are a historical snapshot.

Workshop-era detailCurrent interpretation
Manus 1.5API v2 currently documents manus-1.6, manus-1.6-lite, and manus-1.6-max profiles
API v1 examplesAPI v2 is current; v1 is deprecated and scheduled for removal
Statuses such as pending or completedv2 lifecycle events use running, waiting, stopped, and error
Polling as the main demonstrationPolling remains valid; signed webhooks are the better production notification path
Context supplied mainly per taskv2 also supports Projects, connectors, skills, pre-uploaded files, and structured output
Product memory discussed as future workProjects can now carry shared instructions and files, and can propose approved updates from completed work
A custom Slack bridgeManus now also offers a built-in Slack integration; custom code is needed only for product-specific behavior

Manus announced that it joined Meta in December 2025. This corporate context can affect procurement or risk review, but it does not change the integration boundary: your application still calls a separately operated hosted agent service and must treat it as an external processor.

The thinnest safe integration has two paths:

  1. A command path creates or continues a task.
  2. An event path receives status changes and routes the result back.
flowchart TB
    U["User in web app, Slack,<br/>email, or internal system"] --> I["Application intake<br/>auth, validation, policy"]
    I --> DB[("Local job and<br/>correlation store")]
    I --> Q["Application queue"]
    Q --> MC["Manus API client"]
    MC --> MT["Manus task runtime"]
    MT --> SB["Cloud sandbox"]
    MT --> CN["Approved connectors,<br/>skills, files, and browser"]
    MT --> WH["Signed webhook"]
    WH --> WR["Webhook receiver<br/>verify, deduplicate, acknowledge"]
    WR --> EQ["Event queue"]
    EQ --> DB
    EQ --> O["Output adapter"]
    O --> U

The database is not merely a cache. It is the application-side source of truth for who requested the work, where replies belong, which permissions were approved, and which events have already been processed.

When task.create succeeds, Manus returns a task_id. Store it before acknowledging the request to the user.

A useful local record contains:

FieldWhy it matters
local_job_idStable identifier exposed by your application
provider and provider_task_idRoutes events to the correct external task
requesting_user_id and tenant_idPreserves ownership and tenant isolation
source_typeWeb, Slack, email, scheduled job, or another channel
source_conversation_idRoutes questions and results to the original conversation
source_message_idSupports threading and deduplication
statusYour normalized application state
provider_statusRaw provider state for debugging
policy_snapshotRecords the permissions and limits used when the task began
created_at, updated_at, expires_atSupports timeout and cleanup behavior
last_event_id or processed event tablePrevents duplicate webhook effects
result_manifestRecords messages, structured data, and copied artifacts

Use a unique constraint on (provider, provider_task_id). Store webhook event IDs in a separate table with a uniqueness constraint if more than one event can be processed per task.

For Slack, the mapping often looks like:

(workspace_id, channel_id, thread_ts) <-> local_job_id <-> manus_task_id

That relationship is what turns a provider callback into a reply in the correct Slack thread. Do not ask the model to reconstruct routing metadata from the conversation.

The current v2 endpoint is asynchronous. The API response confirms creation; it is not the research result.

const response = await fetch("https://api.manus.ai/v2/task.create", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-manus-api-key": process.env.MANUS_API_KEY!,
},
body: JSON.stringify({
title: "Research payment orchestration options",
interactive_mode: true,
share_visibility: "private",
agent_profile: "manus-1.6",
message: {
content: [
{
type: "text",
text: [
"Compare three approaches for durable payment orchestration.",
"Use primary sources, distinguish facts from recommendations,",
"and return links for every material claim.",
].join(" "),
},
],
connectors: ["connector-approved-by-policy"],
},
}),
});
if (!response.ok) throw new Error(`Manus returned ${response.status}`);
const created = await response.json();
await jobs.attachProviderTask(localJobId, created.task_id);

The identifiers in connectors are account-specific connector IDs, not connector names. Resolve them from the current connector inventory and allow only those approved for the tenant and use case.

After persisting the mapping, your own API can return something like:

{
"job_id": "job_7f82",
"status": "accepted"
}

The client can show progress without knowing the Manus API key or provider task ID.

Application state should be explicit. Do not infer completion from the absence of recent messages.

stateDiagram-v2
    [*] --> Accepted
    Accepted --> Running: task created
    Running --> WaitingForInput: clarification requested
    Running --> WaitingForApproval: action confirmation requested
    WaitingForInput --> Running: user message sent
    WaitingForApproval --> Running: action confirmed
    Running --> Completed: stopped with finish
    Running --> Failed: error
    Running --> Cancelled: stop requested
    WaitingForInput --> Expired: input deadline reached
    WaitingForApproval --> Expired: approval deadline reached
    Completed --> [*]
    Failed --> [*]
    Cancelled --> [*]
    Expired --> [*]

Manus v2 reports provider states through status_update events:

Provider stateMeaningApplication action
runningThe agent is still workingRecord progress; do not declare success
waitingThe task needs a message or action decisionInspect waiting_for_event_type
stoppedThe task reached a stopping pointRead results and determine the stop reason
errorThe task failedStore error detail and apply retry or escalation policy

The webhook layer uses a related distinction: a task_stopped event can have stop_reason: "finish" or stop_reason: "ask". A stopped webhook therefore does not always mean final completion.

Keep provider state and local state separate. Your application may classify a technically finished task as delivery_failed if the result could not be stored or posted back to the user.

Polling And Webhooks Serve Different Needs

Section titled “Polling And Webhooks Serve Different Needs”

Polling task.listMessages is useful for:

  • prototypes and command-line tools
  • manual troubleshooting
  • reconciliation after a missed callback
  • interfaces that deliberately refresh status on demand

Polling too frequently wastes quota and creates avoidable latency and load. Use exponential backoff with jitter, stop at a defined deadline, and preserve the last event or cursor you processed.

Webhooks are better for production completion and input notifications because the application does not need to repeatedly ask whether a task changed.

A production handler should:

  1. Read the raw request body.
  2. Verify X-Webhook-Signature and X-Webhook-Timestamp.
  3. Reject stale timestamps.
  4. Parse the event only after verification.
  5. Insert event_id into a deduplication table.
  6. Enqueue processing.
  7. Return HTTP 200 quickly.

Manus currently signs the string below with RSA-SHA256:

{timestamp}.{full_webhook_url}.{sha256_hex(raw_body)}

The official guidance rejects requests more than five minutes from the current time and expects webhook endpoints to respond within ten seconds. Fetch the public key from webhook.publicKey, cache it, and support key refresh. Do not fetch the key for every callback.

Webhook delivery should be at least once from the application’s point of view. Even if a provider usually sends one callback, network retries can produce duplicates. Make state transitions and downstream notifications idempotent.

Also run a periodic reconciliation job. It can query nonterminal jobs that have not received an event recently. Webhooks reduce polling; they should not be the only recovery mechanism.

The waiting state has two different meanings that must not be collapsed.

When waiting_for_event_type is messageAskUser, the agent needs additional information. Show the question to the user and continue the same task with task.sendMessage.

Examples:

  • Which market should the report cover?
  • Should the comparison use current pricing or historical pricing?
  • Which of these ambiguous entities did the user mean?

The reply should be routed from the same authenticated user or another actor explicitly authorized to continue that task.

Other waiting event types represent proposed actions. Use task.confirmAction and validate its confirm_input_schema rather than assuming every event accepts the same payload.

Examples include sending email, changing calendar data, deploying an application, executing a terminal command, or selecting a browser session. New event types may be added, so unknown types should fail closed and enter a manual-review path.

An approval screen should show:

  • the exact action
  • target resource and account
  • important parameters
  • expected side effect
  • which user and agent initiated it
  • when the approval expires

Approval must be bound to the displayed parameters. If the action changes, obtain a new approval. See Agent Identity and Delegated Access for the full authorization model.

A common integration mistake is to send every available file, connector, and conversation message “just in case.” More context is not automatically better. It increases cost, expands the security boundary, and can make the agent follow irrelevant or malicious instructions.

Choose the narrowest suitable context mechanism:

MechanismUse it forImportant boundary
Task promptGoal, scope, output criteria, and current requestKeep secrets and routing metadata out
Inline file URL or base64Small task-specific inputCurrent v2 limit is 20 MB for these paths
Pre-uploaded file_idLarger task-specific filesCurrent upload path supports files up to 512 MB
ProjectRepeated work with shared instructions and reference filesProject context applies to every task in that project
ConnectorControlled access to an external account or data sourcePass an explicit approved connector allowlist
SkillReusable procedure or domain behaviorTreat skill instructions as versioned code or policy
BrowserWork requiring an authenticated or interactive browserBrowser access can expose session data and enable side effects
Structured-output schemaMachine-readable result contractExtraction happens after the agent run; it does not constrain every action

Projects Are Scoped Memory, Not Universal Memory

Section titled “Projects Are Scoped Memory, Not Universal Memory”

Projects apply shared instructions to related tasks. Manus also documents a newer feature that can review a completed conversation and propose updates to Project instructions, files, or skills. A person approves the changes before they affect later tasks.

This is useful organizational memory, but it should not be described as an agent remembering everything:

  • the knowledge is scoped to a Project
  • proposed updates require authorization
  • only selected reusable information is promoted
  • source files and instructions can still become stale
  • sensitive or temporary details should not automatically become permanent context

Treat Project updates like documentation changes: review them, preserve provenance, and remove obsolete rules.

If connectors are omitted, Manus can resolve defaults from the Project or account. That is convenient in the interactive product but risky in a multi-tenant or policy-sensitive integration.

Prefer to resolve and pass a connector list explicitly. The application should decide which connector may be used for this user, tenant, and task. OAuth authorization proves that an account was connected; it does not prove that every task should access it.

API keys, refresh tokens, session cookies, and database passwords should stay in trusted infrastructure. Use connector authorization, server-side secret stores, or a narrowly scoped tool boundary. Do not serialize credentials into prompts, files, agent memory, or logs.

Authentication Depends On Who Owns The Integration

Section titled “Authentication Depends On Who Owns The Integration”

Manus v2 supports two main authentication patterns:

PatternAppropriate use
API key in x-manus-api-keyYour own backend, internal scripts, or a single-account integration
OAuth bearer tokenA third-party application acting for different Manus users

An API key has broad access to its account and belongs only on the server. Store it in a secret manager, rotate it, and never expose it to a browser or Slack client.

For a product used by external customers, use the Manus Open App OAuth flow and request only necessary scopes. A token with the narrower create_task scope is limited to tasks created by that Open App. Broader task-management, connector, project, and browser scopes should be requested only when the product actually needs them.

The same principle applies inside your application: the Manus credential identifies the integration, while your own authorization layer determines which local user may create, read, continue, approve, cancel, or share a particular task.

Keep task visibility private unless sharing is an intentional product feature. A public share URL is a data-release decision, not a presentation preference.

An agent can produce three kinds of output:

  1. Human-readable message such as a research summary.
  2. Artifacts such as PDFs, spreadsheets, presentations, or generated files.
  3. Structured data for another program.

Do not force one representation to serve all three consumers.

Render the final message in the original conversation and preserve source links. Channel adapters may need to split long text, convert Markdown, or post a short summary plus an artifact link.

Treat generated download URLs as temporary external references. Copy required artifacts into storage controlled by your application, scan them, record content type and checksum, and enforce the user’s authorization when serving them later.

The Manus file-upload documentation currently says uploaded files are automatically deleted after 48 hours. Provider retention rules can change, so the application should not rely on provider storage as its permanent archive.

For automation, request structured_output_schema when creating the task. Manus runs the agent normally and then performs a post-processing extraction when the task finishes.

That has two consequences:

  • the JSON contract makes result consumption easier
  • it does not constrain the agent’s browsing, tool selection, or intermediate behavior

The current schema subset requires an object root, all properties in required, and additionalProperties: false. Validate the result again in your application. A schema-valid value can still be factually wrong.

{
"type": "object",
"properties": {
"recommendation": { "type": "string" },
"confidence": { "type": "number" },
"source_urls": {
"type": "array",
"items": { "type": "string" }
}
},
"required": ["recommendation", "confidence", "source_urls"],
"additionalProperties": false
}

Use deterministic application code for calculations, policy decisions, money movement, and other operations that should not depend on a generated interpretation.

Slack: Built-In Integration Or Custom Bridge?

Section titled “Slack: Built-In Integration Or Custom Bridge?”

The workshop uses Slack to show the general integration pattern. Manus now has an official Slack integration, so first decide whether custom code adds real value.

Use the built-in integration when:

  • users only need to invoke Manus and receive normal results in Slack
  • Manus’s standard thread behavior and permissions are acceptable
  • there is no product-specific database or workflow to update

Build a custom bridge when:

  • task creation depends on your own authorization or business rules
  • requests need preprocessing, templates, or tenant-specific context
  • results must update internal records as well as Slack
  • approval must go through your product’s policy engine
  • you need custom observability, retention, billing, or audit behavior
  • one task must coordinate across several channels or systems

A custom Slack flow should be event-driven:

sequenceDiagram
    participant U as Slack user
    participant A as Application
    participant D as Job database
    participant M as Manus API
    U->>A: Mention bot with research goal
    A->>A: Authenticate and validate policy
    A->>M: task.create
    M-->>A: task_id
    A->>D: Store Slack thread and task mapping
    A-->>U: Research task accepted
    M->>A: Signed task_stopped webhook
    A->>A: Verify and deduplicate event
    A->>D: Load original Slack thread
    A-->>U: Post question or final result in thread

Slack may retry its own events too. Deduplicate incoming Slack event IDs separately from Manus webhook event IDs.

A hosted agent removes some infrastructure work, but it introduces a remote dependency. Plan for partial failure at every boundary.

FailureDefensive behavior
Task creation times outReconcile before creating a duplicate; store provider request IDs when available
Rate limitExponential backoff with jitter and bounded retries
Webhook arrives twiceUnique event_id; idempotent state transition and delivery
Webhook is missedPeriodic reconciliation with task messages or detail endpoints
Events arrive out of orderApply transitions by event identity and current state, not arrival assumptions
Task waits indefinitelyInput and approval deadlines with user reminders or expiry
User cancelsStop provider task and mark local cancellation intent immediately
Result cannot be deliveredPersist result and retry only the delivery adapter
Connector authorization expiresSurface a reauthorization state rather than silently removing context
Generated file expiresCopy required artifacts into controlled storage promptly
Provider behavior changesContract tests, pinned API version, and a dated compatibility review

Current Manus rate limits are per user and shared across that user’s API keys. The exact numbers are version-sensitive. Read response errors, follow the current rate-limit documentation, and avoid treating today’s limits as permanent constants in product documentation.

Track at least:

  • task creation success and latency
  • time in running and waiting states
  • clarification and approval frequency
  • completion, error, cancellation, and expiry rates
  • webhook verification and duplicate counts
  • credits or cost per accepted result
  • connector and browser usage
  • artifact download and delivery failures
  • user-rated or evaluator-rated result quality

Operational success is not the same as research quality. A task can complete cleanly and still return weak, stale, or unsupported conclusions.

Manus is a reasonable fit when the product needs a managed general agent rather than only text generation.

It is strongest when:

  • tasks require web research and synthesis across many steps
  • users expect reports, files, presentations, or other artifacts
  • the agent needs a hosted sandbox and tool ecosystem
  • connectors and browser-based work are central to the use case
  • the team wants to avoid building and operating a complete agent runtime
  • occasional human clarification fits the product experience
  • vendor-hosted execution and data processing meet policy requirements

The central benefit is speed of integration. Your application delegates the research execution loop while retaining its own user experience and business controls.

A hosted general agent is not the right default for every feature.

Choose a direct model API when:

  • one bounded prompt produces the answer
  • latency must be measured in seconds
  • your code already owns the required retrieval and tools
  • every tool call and token needs tight control
  • a simpler failure model is more important than agent autonomy

Choose a self-hosted agent framework when:

  • you need to inspect or customize every loop decision
  • models, tools, memory, and execution environments must be replaceable
  • data cannot be processed by the hosted provider
  • domain-specific orchestration matters more than general autonomy
  • your team is prepared to operate sandboxes, queues, state, and observability

Add a durable workflow system such as Temporal when:

  • the application’s multi-service process must survive deployments and crashes
  • work spans Manus plus databases, payments, approvals, or other agents
  • retries, timers, compensation, and long waits need explicit semantics
  • the provider task is only one step in a larger business workflow

Manus and Temporal solve different layers. Manus can perform the research task; Temporal can durably coordinate when to start it, wait for it, route approvals, combine it with other services, and recover the surrounding workflow. See Durable AI Agents with Temporal.

Use ordinary deterministic services when:

  • the workflow is a known sequence of API calls
  • correctness depends on explicit business rules
  • there is no meaningful judgment or open-ended research

An agent should earn its place by handling uncertainty. It should not replace code that is already easy to specify and test.

Prototype The Task Before Building The Integration

Section titled “Prototype The Task Before Building The Integration”

The workshop’s most practical lesson is to test the research behavior in the Manus product before wrapping it in Slack, webhooks, queues, and databases.

Use this sequence:

  1. Run representative tasks manually in Manus.
  2. Identify what context produces good results.
  3. Record common clarification questions and failure modes.
  4. Define the expected human output and machine-readable contract.
  5. Decide which connectors and actions are actually required.
  6. Build an evaluation set from real examples.
  7. Only then automate task creation and delivery.

This separates two problems:

  • Can the agent perform the task well?
  • Can the application operate the task reliably and securely?

If the first answer is no, more integration code will not fix it.

The durable lessons are not the live demo details. They are the system boundaries:

  • long-running agents require asynchronous application design
  • the provider task ID must be correlated with the original user and conversation
  • polling is useful for prototypes; webhooks are better for production notifications
  • follow-up messages should continue the same task rather than start unrelated work
  • files and external data are explicit context choices
  • human questions are normal lifecycle states, not exceptional failures
  • final messages and generated artifacts need separate delivery handling
  • the web product is a useful place to validate a task before API automation

The workshop’s Manus 1.5 code, v1 payloads, status names, pricing, live-coding issues, and product roadmap claims are intentionally not reproduced here.

Before development:

  • Confirm that a hosted agent is preferable to a direct model call or deterministic service.
  • Test representative tasks manually and define quality criteria.
  • Review current API version, profiles, limits, and retention rules.
  • Decide whether the built-in integration already satisfies the use case.
  • Complete vendor, privacy, residency, and procurement review.

Before task creation:

  • Authenticate the local user and tenant.
  • Validate goal, files, connectors, browser access, and expected output.
  • Keep credentials and routing metadata out of prompts.
  • Default task sharing to private.
  • Create a local job record and define deadlines and cancellation behavior.

Before production:

  • Persist the provider task ID and conversation mapping atomically.
  • Verify webhook signature and timestamp against the raw body.
  • Deduplicate webhook and channel events.
  • Queue callback processing and acknowledge quickly.
  • Reconcile stale nonterminal jobs independently of webhooks.
  • Distinguish clarification from action approval.
  • Fail closed on unknown confirmation event types.
  • Copy required artifacts into controlled storage.
  • Validate structured output semantically as well as syntactically.
  • Add cost, latency, quality, failure, and audit monitoring.
  • Test cancellation, duplicate events, missed events, expired approval, and delivery failure.

Diagram viewer