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.
The Starting Mental Model
Section titled “The Starting Mental Model”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 call | Hosted agent task |
|---|---|
| Usually one request and one response | Asynchronous task with several events |
| Your code explicitly calls every tool | The agent can select and sequence available tools |
| Usually completes in seconds | May run for minutes or longer |
| Returns text or a structured response | May return messages, files, links, and structured data |
| Your process owns the complete loop | The provider runs part of the loop in its own environment |
| Missing information usually produces a best-effort answer | The task may stop and ask a question |
The useful abstraction is therefore:
Create task -> persist task ID -> observe events -> supply input if needed -> deliver resultDo 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.
What Manus Adds Beyond An LLM
Section titled “What Manus Adds Beyond An LLM”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.
What Changed Since The Workshop
Section titled “What Changed Since The Workshop”The workshop remains useful for its architectural ideas, but its product details are a historical snapshot.
| Workshop-era detail | Current interpretation |
|---|---|
| Manus 1.5 | API v2 currently documents manus-1.6, manus-1.6-lite, and manus-1.6-max profiles |
| API v1 examples | API v2 is current; v1 is deprecated and scheduled for removal |
| Statuses such as pending or completed | v2 lifecycle events use running, waiting, stopped, and error |
| Polling as the main demonstration | Polling remains valid; signed webhooks are the better production notification path |
| Context supplied mainly per task | v2 also supports Projects, connectors, skills, pre-uploaded files, and structured output |
| Product memory discussed as future work | Projects can now carry shared instructions and files, and can propose approved updates from completed work |
| A custom Slack bridge | Manus 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.
A Production Reference Architecture
Section titled “A Production Reference Architecture”The thinnest safe integration has two paths:
- A command path creates or continues a task.
- 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.
Persist Correlation Before Returning
Section titled “Persist Correlation Before Returning”When task.create succeeds, Manus returns a task_id. Store it before acknowledging the request to the user.
A useful local record contains:
| Field | Why it matters |
|---|---|
local_job_id | Stable identifier exposed by your application |
provider and provider_task_id | Routes events to the correct external task |
requesting_user_id and tenant_id | Preserves ownership and tenant isolation |
source_type | Web, Slack, email, scheduled job, or another channel |
source_conversation_id | Routes questions and results to the original conversation |
source_message_id | Supports threading and deduplication |
status | Your normalized application state |
provider_status | Raw provider state for debugging |
policy_snapshot | Records the permissions and limits used when the task began |
created_at, updated_at, expires_at | Supports timeout and cleanup behavior |
last_event_id or processed event table | Prevents duplicate webhook effects |
result_manifest | Records 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_idThat 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.
Creating A Current Manus Task
Section titled “Creating A Current Manus Task”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.
Treat The Task As A State Machine
Section titled “Treat The Task As A State Machine”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 state | Meaning | Application action |
|---|---|---|
running | The agent is still working | Record progress; do not declare success |
waiting | The task needs a message or action decision | Inspect waiting_for_event_type |
stopped | The task reached a stopping point | Read results and determine the stop reason |
error | The task failed | Store 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
Section titled “Polling”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
Section titled “Webhooks”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:
- Read the raw request body.
- Verify
X-Webhook-SignatureandX-Webhook-Timestamp. - Reject stale timestamps.
- Parse the event only after verification.
- Insert
event_idinto a deduplication table. - Enqueue processing.
- 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.
Clarification Is Not Approval
Section titled “Clarification Is Not Approval”The waiting state has two different meanings that must not be collapsed.
Clarification
Section titled “Clarification”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.
Action confirmation
Section titled “Action confirmation”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.
Context Is A Designed Input Surface
Section titled “Context Is A Designed Input Surface”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:
| Mechanism | Use it for | Important boundary |
|---|---|---|
| Task prompt | Goal, scope, output criteria, and current request | Keep secrets and routing metadata out |
| Inline file URL or base64 | Small task-specific input | Current v2 limit is 20 MB for these paths |
Pre-uploaded file_id | Larger task-specific files | Current upload path supports files up to 512 MB |
| Project | Repeated work with shared instructions and reference files | Project context applies to every task in that project |
| Connector | Controlled access to an external account or data source | Pass an explicit approved connector allowlist |
| Skill | Reusable procedure or domain behavior | Treat skill instructions as versioned code or policy |
| Browser | Work requiring an authenticated or interactive browser | Browser access can expose session data and enable side effects |
| Structured-output schema | Machine-readable result contract | Extraction 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.
Connectors Need Explicit Selection
Section titled “Connectors Need Explicit Selection”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.
Do Not Pass Credentials In Prompts
Section titled “Do Not Pass Credentials In Prompts”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:
| Pattern | Appropriate use |
|---|---|
API key in x-manus-api-key | Your own backend, internal scripts, or a single-account integration |
| OAuth bearer token | A 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.
Design The Output For Its Consumer
Section titled “Design The Output For Its Consumer”An agent can produce three kinds of output:
- Human-readable message such as a research summary.
- Artifacts such as PDFs, spreadsheets, presentations, or generated files.
- Structured data for another program.
Do not force one representation to serve all three consumers.
Human-readable results
Section titled “Human-readable results”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.
Artifacts
Section titled “Artifacts”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.
Structured results
Section titled “Structured results”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.
Reliability And Operational Controls
Section titled “Reliability And Operational Controls”A hosted agent removes some infrastructure work, but it introduces a remote dependency. Plan for partial failure at every boundary.
| Failure | Defensive behavior |
|---|---|
| Task creation times out | Reconcile before creating a duplicate; store provider request IDs when available |
| Rate limit | Exponential backoff with jitter and bounded retries |
| Webhook arrives twice | Unique event_id; idempotent state transition and delivery |
| Webhook is missed | Periodic reconciliation with task messages or detail endpoints |
| Events arrive out of order | Apply transitions by event identity and current state, not arrival assumptions |
| Task waits indefinitely | Input and approval deadlines with user reminders or expiry |
| User cancels | Stop provider task and mark local cancellation intent immediately |
| Result cannot be delivered | Persist result and retry only the delivery adapter |
| Connector authorization expires | Surface a reauthorization state rather than silently removing context |
| Generated file expires | Copy required artifacts into controlled storage promptly |
| Provider behavior changes | Contract 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.
Why Use Manus?
Section titled “Why Use Manus?”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.
Why Not Always Use Manus?
Section titled “Why Not Always Use Manus?”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:
- Run representative tasks manually in Manus.
- Identify what context produces good results.
- Record common clarification questions and failure modes.
- Define the expected human output and machine-readable contract.
- Decide which connectors and actions are actually required.
- Build an evaluation set from real examples.
- 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.
What We Keep From The Source Workshop
Section titled “What We Keep From The Source Workshop”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.
Implementation Checklist
Section titled “Implementation Checklist”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.
References
Section titled “References”- Source workshop: Building Intelligent Research Agents with Manus
- Manus introduction
- Manus API v2 introduction
- Create a Manus task
- Manus task lifecycle
- Manus webhook overview
- Manus webhook security
- Manus authentication
- Manus Open App OAuth guide
- Manus connectors
- Manus structured output
- Manus file upload
- Manus Projects
- Projects that learn from approved updates
- Manus Slack integration
- Manus rate limits