Skip to main content
Melso Agents is available only internally or by private invitation. Agents-specific features require existing access. For the autónomo fiscal service, see Get started.
Create and manage durable Task conversations. {id} accepts a Task UUID or identifier on routes that accept identifiers. Use UUIDs for /input, conversation paging and queue routes. Task status summarizes lifecycle, execution and attention. See the Task, Run and fiscal state tables; a failed Run is an attention reason, not a Task status. input is the opening message. description is a separately edited summary. In an Agents company, supply both input and execution to start a Run. In an autónomo or empresa company, input can start a Run using the company’s default execution. To save without running in either case, omit execution and set start: false. The top-level start flag controls default execution; it supplies no funding settings and does not cancel an explicit execution object. Read run_id from the creation response only when a Run was created; a client_request_id replay returns the same run_id. Follow-ups go to POST /api/tasks/{id}/input, which accepts its own client_request_id with the same retry contract.

Persistent Task watches

Watches resume a Melso-managed Task conversation when another accessible Task publishes an event. The subscriber is inferred from the current Run credential; the path identifies the watched Task. Parent links only organize Tasks. External OAuth clients have no durable subscribing conversation and cannot use these routes; use Webhooks for external notifications. Registration returns immediately. End the current agent turn after it succeeds. Watches persist across Runs until explicitly removed or the subscriber closes. Notifications wait while the subscriber is busy, paused, or waiting for human input; dispatch revalidates access and execution authority. No acknowledgment is required. Isolated Task Runs cannot manage watches.

Direct browser uploads (up to 1 GiB)

On S3-compatible storage or a configured GCS mounted bucket, browser clients upload files directly to the object bucket. Call POST /api/uploads/direct with JSON filename, content_type, size_bytes, and optional task_id, message_id, and run_id. Send company context as usual. The response has id, upload_url, and headers. PUT the raw file bytes to that URL with the returned headers, then call POST /api/uploads/direct/{id}/complete with the same Melso credentials and company context. Completion verifies the object size and current access before returning an AttachmentResponse. Files are invisible until completion. S3 uses a one-hour signed PUT URL; GCS uses a resumable session URL that acts as a bearer capability. The browser sets Content-Length from the file automatically. The S3 signature binds it to the declared size; GCS receives the declared size when the resumable session starts. Temporary objects are copied to a permanent key at completion so the upload URL cannot replace a completed attachment. Expired temporary objects are reclaimed on later upload starts. Use direct upload for larger files, up to 1 GiB, when storage supports it. For smaller files, or when direct upload is unavailable, use the multipart upload route in the Files reference, keeping the complete request under 100 MiB. The two routes have different size limits.

Isolated Tasks

Set isolated: true when creating a Task that one Melso account runs on behalf of someone else, such as an integration that turns each of its end users’ conversations into a Task. We recommend it whenever a single account creates Tasks for many end users. The flag is fixed at creation: PUT /api/tasks/{id} rejects it, and every TaskResponse reports it. For an isolated Task, Melso guarantees:
  • Other Runs cannot see it. A Run of any other Task gets 404 on every route that addresses the isolated Task, and the Task never appears in its lists, search, children or child progress.
  • Its own Runs stay inside it. They can read the Task, its messages and attachments, upload attachments to it, ask the human (interactions), and use the Area’s connected apps and repository checkout. Any other Task is a 404, and lists and search return at most this Task. Everything else returns 403 with "code": "isolated_task_scope": creating Tasks, including child Tasks; changing this Task (fields, status, metadata, outputs, messages, follow-up input); reading or changing its Task MCP servers; and changing the company (Areas, automations, Library knowledge, artifacts, skills, secrets and secret requests, memories, connected-app management, settings, MCP servers, GitHub).
  • No duplicate matching. The duplicate-title check never compares an isolated Task with other Tasks.
  • Pull requests follow the Run’s branch. A pull request links to, and on merge completes, an isolated Task only when it comes from that Task’s own Run branch (agent/<name>/<first 8 characters of the Task ID>) in the same repository. A pull request from that branch never links, reviews or completes another Task, and an isolated Task never gets a Melso review child Task.
Isolated Runs also receive no memory tools, and their instructions and built-in skills omit cross-Task and company-management guidance. Isolation applies per Task. Create child Tasks of an isolated Task with isolated: true too: an ordinary child stays visible to other Runs, and its parent_task_id shows the isolated parent’s ID. Your own API calls (company API key, personal access token or browser session) and company MCP credentials keep normal company and Area access, so the integration that creates isolated Tasks still lists, reads and manages every one of them. Isolation keeps Tasks apart from each other, not from the company. Company-level configuration is shared input to every Run, isolated or not: company context, Area instructions and resources, company skills and plugins, plus Secrets items shared with the company or Area and connected apps allowed for the Area. Company members can change that configuration, and so can the Runs of their non-isolated Tasks, so an isolated Run cannot count on it being private or unchanged. Keep end-user data out of it. If an integration needs strict separation from everything else in a company, give it a dedicated company. Melso recognizes a Run’s pull requests only by branch name. A Run that can push to a repository can open a pull request from another branch, and that pull request still links to, and on merge completes, any ordinary Task it names. Where isolated and ordinary Tasks share a repository, check a pull request’s linked Tasks before you merge it.

Task MCP servers

Give one Task’s Runs MCP servers of their own, such as your wiki, issue tracker or CRM authenticated with a secret you mint for that Task, or connectors your end user picked for a message. Send mcp_servers with POST /api/tasks, replace the whole set with PUT /api/tasks/{id}/mcp-servers and read it with GET /api/tasks/{id}/mcp-servers. They work for isolated and ordinary Tasks. McpServerInput is one of:
  • Remote streamable HTTP: {name:string, url:string, headers?:{[name:string]:string}}.
  • stdio: {name:string, command:string, args?:string[], env?:{[name:string]:string}}. The command runs inside the Run’s sandbox, so it must be available there, for example npx.
McpServerSummary is {name:string, transport:"http"|"stdio", url?:string, header_names?:string[], command?:string, args?:string[], env_names?:string[]}. url, command and args are returned as given; header and env names are sorted. Values are never returned. The mcp_servers field contract owns the count, transport and sealed-size limits. This example omits execution and sets start: false, saving the Task and server configuration without a Run. Replace the URL with a server you control:
POST /api/tasks
To create and run an Agents Task in one request, add an opening input and an execution object, and remove start: false. Put funding choices inside execution; mcp_servers remains top-level. Complete the funding setup in the API quickstart first. An authorized GET /api/tasks/{id}/mcp-servers returns the corresponding summary:
GET /api/tasks/{id}/mcp-servers response
Every create and replacement is checked as a whole. For example, if the first server supplies both url and command, validation returns HTTP 400:
PUT /api/tasks/{id}/mcp-servers response 400
Choose one transport and retry with its fields. Validation messages identify the offending field without returning secret header or environment values. The rules are:
  • At most 10 servers per Task. name matches ^[a-z0-9][a-z0-9-]{0,62}$, is unique within the Task, and cannot use a platform-reserved name.
  • Each server has exactly one of url or command. headers apply only to remote servers; args and env only to stdio servers. Unknown fields are refused.
  • url is an absolute https URL without whitespace or credentials. It is returned as given, so send secrets as headers, not in the URL.
  • Header names are HTTP field names, each at most once ignoring case, and header values contain no line breaks or other control characters except tab.
  • command is not blank and contains no control characters. args and env values contain no NUL characters. Env names use letters, digits and underscores and do not start with a digit.
  • The sealed set of one Task is at most 64 KiB; a larger one is refused with 413.
How Runs use them:
  • When a Run of the Task is claimed, its MCP configuration holds the Task’s servers next to the Company-enabled servers and the servers granted to the Task’s Area. A Task server whose name equals a Company or Area server’s name replaces that server for this Task’s Runs.
  • A replacement applies to Runs claimed after it. A Run already running keeps the servers it started with.
  • Header and env values are write-only. Melso encrypts them, never returns them in a response, error, log or event, and redacts them from the Run’s output the way it redacts the Secrets values a Run receives.
  • The values still reach the Run’s harness configuration, as company MCP servers’ values do, so the agent in the Run can read them. Mint each secret scoped to its Task and short-lived, have your MCP server refuse it once the Task has no live Run, and rotate it by replacing the set.
  • Only company owners and admins (browser session or personal access token) and the company’s API keys set or clear them, with mcp_servers on POST /api/tasks or with PUT: a stdio server’s command runs, and a remote server is called, in every later Run of the Task, including Runs other members execute. Anyone else gets 403 code: "task_mcp_servers_forbidden". A role change or key revocation that commits while a write is in progress refuses it. Human callers and company keys with Task read access may list the summaries with GET; Run tokens are excluded from this read permission.
  • Every Run token gets 403 on both routes and on POST /api/tasks with mcp_servers, including a Run of the Task itself (isolated_task_scope for a Run of an isolated Task). No MCP tool reads or sets them.
  • A client_request_id replay covers mcp_servers: a retry with other servers or other values under the same id returns 409. To tell them apart, Melso stores a SHA-256 of the create body, header and env values included, so use high-entropy secrets.
  • Deleting the Task deletes its servers.

Authentication

Use a company API key, which implies its company, or a personal access token with the X-Workspace-ID header. See Overview and authentication for credential types and token management.

Read and control work

Follow a Task with GET /api/tasks/{id}/stream: one Server-Sent Events connection pushes the Task, its Runs, their trace, the conversation and interactions as they change, and resumes without gaps after a disconnect. Prefer it to polling. Follow a Task’s Runs, not one Run: retries, Cloud lifetime rollovers and pauses add successor Runs, so one Run ending is not the Task’s outcome. GET /api/runs/{runId} reads one Run you already know in the shape GET /api/tasks/{id}/runs lists it. Read the final answer from Task conversation messages, inspect Run messages and events, and use the Run controls to pause, resume or cancel execution.

MCP

For remote MCP with OAuth, start with MCP setup.

Apps built by Tasks

An ordinary Task can build a static HTML or Vite Artifact, retain its source and publish a stable company or public link. Later Tasks retrieve the source through the Artifact MCP catalog and deploy another version. Isolated Runs cannot deploy or manage Artifacts. See Artifacts through MCP. Human sessions and PATs can use the matching JSON endpoints POST /api/artifacts/{list,get,deploy,manage,launch,renew,data} with the selected company. Direct company API keys are not supported on this surface; Runs use their existing MCP credentials. Public viewers use POST /api/public/artifacts/{shareID}/{launch,renew,data} with anonymous publication authority, including when the visitor is signed in. App table access is restricted by explicit dataset grants and does not expose the general API.

Execution identity

An admin company API key may supply execution_identity_id at create time for an isolated: true Task. It must identify an active managed execution customer owned by that key’s integration in the same company. The field is immutable and is returned in Task responses. Task creation and follow-up retries remain scoped to their original API caller; all turns use the bound customer’s provider accounts and funding policy. See Managed execution customers. Managed Tasks receive their explicitly configured Task MCP servers and repository broker grants. They do not inherit company or Area MCP servers, connected-app sessions, Secrets items, company repositories, Melso GitHub App credentials or the company private network. Ordinary member Tasks retain their existing resource scope.

Atomic Task context

POST /api/tasks accepts metadata (a flat map of strings, numbers and booleans) and instructions (immutable guidance for all Runs on the Task). The initial metadata bag follows the metadata field contract, with at most 50 keys and the existing 8 KiB JSONB storage limit. Instructions are limited to 32768 UTF-8 bytes and cannot contain NUL. Run credentials cannot configure Task instructions. Both fields are committed before the first Run becomes available and included in the client_request_id replay contract; changing either under the same request ID returns 409 client_request_conflict. Metadata remains editable through the existing single-key metadata routes. Neither field grants execution access; keep credentials in authorized secret storage, never in metadata or instructions.

Customer-managed repository credentials

An admin company key registers only its own integration’s broker through PUT /api/execution-credential-broker with { "endpoint": "https://...", "token": "..." }. Ask Melso to enable your broker’s exact HTTPS origin before registering it. Registration and delivery reject private DNS answers; delivery pins the public address and never follows redirects. GET returns configuration identifiers and the endpoint, without credentials. DELETE revokes the broker and future repository renewals. Task create accepts repositories, each with a canonical GitHub HTTPS url, optional ref, permission (read or write), and credential_reference. Up to 20 grants are fixed at Task creation and override inherited repository lists. The reference identifies the customer’s authorization grant, never a credential. These fields require an admin key and participate in the atomic create/replay contract. Broker execution requires an enabled integration. Melso requests one repository token from the broker with an authenticated JSON POST containing reference, workspace_id, task_id, run_id, repository_url, and permission. The broker must independently authorize the external user and repository on every call, and return { "token": "...", "expires_at": "...", "permission": "read" }. Permission must exactly match the request. The repository credential contract requires expiry more than 30 seconds and at most 70 minutes after the exchange’s validation time. Errors and remote bodies are never forwarded to agents. Renewal requires a live, unchanged Run attempt and its signed 24-hour grant. The request must identify exactly one repository. The managed Git/gh helper replaces inherited owner/host GitHub authentication so read grants receive only read tokens. Revocation and broker rotation are rechecked after each exchange.

Execution bound to an accepted input

POST /api/tasks/{id}/input accepts optional execution using the create execution schema and optional mcp_servers using the Task MCP schema. The selected execution and encrypted MCP configuration belong to the accepted Run and its retries. They do not change the Task’s next-run defaults. An explicit empty MCP array disables Task-local MCP for that turn; omission snapshots the current Task-local servers. Company and Area MCP access still follows their existing policies. execution.funding_source on create or input may select account, gateway, api_key or custom. Omission selects an authorized method at acceptance. Cloud admission rechecks authorization, availability and budget for the bound method; a disabled or unavailable method fails instead of switching to an unrelated method. Account election continues to select an authorized healthy account within the selected account method. Funding cannot be changed by the Task’s next-run picker endpoint. execution.provider_account_id chooses one authorized provider account for that accepted Run. It implies funding_source: "account" and rejects another funding source. The account must belong to the execution identity or have an explicit share to it and match the harness. Disabled, revoked, reconnecting or exhausted accounts fail closed; an explicit choice never falls back to another account or the Gateway. Send the account ID on each turn that needs that choice. It does not change the Task defaults or the member’s preferred account. Execution, funding and MCP changes are included in the client_request_id replay contract: an exact retry returns the original receipt, and a changed selection returns 409 client_request_conflict. Keep one request ID per intended input, including its full execution and MCP selection.

Settled execution usage

GET /api/runs/{run_id}/usage has the same company and Task access rules as reading the Run, including company API keys. It returns the funding source, selected account and execution identity, and customer_billed_ticks from actual wallet transactions. One tick is $0.0000000001; amounts are decimal strings. receipts contains immutable wallet receipt_id values and signed billed amounts: charges are positive and refunds are negative. Deduplicate each receipt_id, including adjustment receipts. usage_id groups updates to one operation. reported_model_cost_ticks is the worker’s model-cost report; it is separate from customer billing, especially for personal subscriptions and BYOK. No supplier costs, credentials, request bodies or raw receipt metadata are returned. final stays false while the Run is active, a Gateway hold is unresolved, compute is open, or canonical operation totals have not reached the wallet ledger. Closed compute charged at its pinned rate can be settled with estimated supplier evidence. estimated remains explicit on those wallet receipts. as_of identifies the consistent snapshot. Continue periodic reconciliation after finalization to receive later provider corrections and refunds; they produce new receipt IDs.

API reference

Request fields, response types and endpoint permissions are defined in the Tasks reference. See Pagination for list conventions, or start with the API quickstart.

Creation fields

The Tasks endpoint reference owns the complete creation schema. Alongside title, input, description, area_id, parent_task_id, attachment_ids, client_request_id, allow_duplicate, callback_url, start, isolated and mcp_servers, it includes metadata, instructions, repositories and execution_identity_id. The execution object includes harness, model controls, funding_source and provider_account_id; funding choices are nested inside execution, not top-level fields. GET /api/tasks?status=done filters closed completed Tasks. Other status values do not filter the derived statuses; use the state table to interpret each result. Optional Task response flags such as has_pending_interaction can be omitted when false. These excerpts mean false/absent and true/present respectively: