Build and deploy computer vision applications with Roboflow. Organize and annotate image datasets, generate training data, train custom object detection and segmentation models, run inference on images and video, and deploy vision workflows to cloud or edge devices.
Try asking
Encrypted at rest, isolated from the model
Resolved from an AES-256-GCM vault at the moment of the call and attached to the request — the model never sees the secrets.
Chat with the Roboflow AI agent. Use this tool for: - **Roboflow Q&A** — the agent has the full Roboflow documentation indexed (SDKs, REST API, deployment options, training, batch processing, Universe, blocks, pricing, etc.). Ask it anything about how Roboflow works. - **Advanced workflow building** — workflows complex enough that composing the JSON yourself is impractical. The agent knows every block and connection pattern. - **Solution planning** — pass ``mode="plan"`` and the user's problem; the agent uses a stronger planning model to scope a CV solution end-to-end before any building happens. For straightforward workflows you can construct yourself, the direct ``workflow_*`` tools are fine — you don't have to route every workflow through the agent. ## Conversation flow The agent runs a multi-step conversation. It may ask clarifying questions, recommend a model, or (in plan mode) produce a plan for confirmation. Pass the returned ``conversation_id`` back on follow-up calls to keep context. Use ``agent_conversations_list`` and ``agent_conversation_get`` to find and resume past conversations. ## Long runs Complex turns (large workflow builds/edits) can take several minutes. When the agent does not finish quickly, this tool returns ``{"status": "running", "run_id": ...}`` instead of blocking. Call ``agent_chat_result`` with that ``run_id`` repeatedly until the status is no longer ``running``; the run keeps executing server-side in the meantime. Do NOT re-send the same message with agent_chat, that would start a second, duplicate run. ## What the agent changes in the workspace The agent never runs a workflow or model inference; it only validates the workflows it writes. - A **new** workflow is saved and immediately runnable by its URL slug. - An **edit** to an existing workflow is saved as a **draft**. The published version that callers using the workflow by id hit is unchanged until the user publishes it with ``agent_workflow_publish`` (pass the workflow ``url`` returned in the chat response). ``mode="plan"`` only reads and plans; it changes no workflow. ## Running an agent-built workflow Run a saved workflow with ``workflows_run(workflow_id=..., images=...)``. It always runs the published version, so publish an edit first when the user has authorized it. If execution fails, follow the specific permission or upstream error; do not assume OAuth is unsupported. If the user prefers visual testing, open the workflow's ``app_url``. ## Where to open a workflow in the Roboflow UI Each workflow in the ``workflows`` array has an ``app_url`` field with the canonical, environment-aware Roboflow UI URL. ``app_url`` is the authoritative link for a workflow; URLs embedded in the agent's ``text`` reply may not match the current environment. ## Response shape When the run finishes within the inline wait: - ``status`` — ``"completed"``. - ``text`` — the agent's reply. - ``workflows`` — workflows created or edited in this turn, each with ``id``, ``name``, ``url`` (slug), ``app_url`` (clickable Roboflow UI URL — use this), and ``specification`` (the full JSON of the saved version or draft). - ``conversation_id`` — pass back to continue the conversation. When the run is still going: ``status`` is ``"running"`` and ``run_id`` is the handle to pass to ``agent_chat_result``.
Collect the result of an agent_chat run that was still working. Waits briefly for the run to finish, then returns either the completed chat response (same shape as ``agent_chat``) or ``{"status": "running", "run_id": ...}``. Keep calling with the same ``run_id`` until the status is no longer ``running``. The run keeps executing server-side between calls; polling never restarts or duplicates it. A ``"severed"`` status means the connection to the run was cut mid-flight; the run usually still finishes server-side, so read the reply from the conversation (``agent_conversation_get``) instead of re-sending the message.
List Roboflow agent conversations in the workspace. Returns conversation metadata (id, name, source, timestamps, linked workflow ids). Use ``agent_conversation_get`` to load the full message history for a single conversation, or pass the conversation id back to ``agent_chat`` to resume it.
Get a single agent conversation with its message history. Returns the conversation metadata and the ordered list of the most recent ``message_limit`` messages (role + text parts), plus ``total_messages`` with the full history size. Pass the same ``conversation_id`` back to ``agent_chat`` to continue the conversation.
Publish the latest agent-edited draft of a workflow. The agent never publishes its edits to an existing workflow; it saves them as a draft. This tool promotes the latest draft to a published version so it goes live for callers using the workflow by id (``workflows_run``). Errors with 400 if there is no draft to publish (i.e. the published version already matches the latest draft). Returns ``{ workflowId, workflowUrl, versionId, status }``.
Discover Roboflow workflow guidance when native skills/list is unavailable. Use for Roboflow workflows and interactive apps. Returns descriptions and file manifests, not full instructions. Read the relevant SKILL.md with resources/read, or read_skill when the client cannot read resources. Follow nextCursor to list additional skills.
Read server-hosted workflow or app instructions when MCP resources are unavailable. Load the relevant SKILL.md before following its workflow; retrieve referenced files only as needed, using their manifest URIs on this same server. Returns the actual text (or base64 blob for binary files). This reads guidance only: it does not execute scripts, install skills, or grant tool permissions.
List projects in the workspace associated with the credential. Returns ``{ projects, total, limit, offset }`` where ``projects`` holds up to ``limit`` entries (id, name, type, image count, and more) and ``total`` counts the usable projects across all pages. Page with ``offset`` when ``total`` exceeds ``limit``.
Create a new computer vision project, including Action Recognition and Anomaly Detection. Action Recognition projects are video-only. Anomaly Detection requires workspace enablement and creates fixed, single-label normal/anomalous classes. Active anomaly detection and ordinary projects cannot use the same annotation group. The annotation group is not private to the project: projects that use the same group share annotations on the images they have in common. If an active project of the same kind already uses the name, the new project silently joins that group. Projects in the Trash are excluded from the kind check, so a new project can also join a group used by a trashed project of either kind. Images uploaded to the new project that are already stored in the workspace come with their annotations from that group, and uploading them with annotations fails with "Image was already annotated" unless image_upload's annotation_overwrite is set. Unless the user wants shared annotations, check the annotation values from projects_list and trash_list first and pick a name no other project uses. Returns the created project's id, name, type, and url.
Get dataset health check for a project. Running this for the first time or with regenerate=True might take up to a couple minutes. Returns class balance, image quality issues, annotation statistics, and other dataset health metrics.
Get detailed info about a project including versions, classes, splits, and trained models. Returns full project details with workspace, project info, versions, and classes.
Delete a project, moving it to the workspace Trash. This is a soft delete: the project (including its versions, images, and models) stays in the Trash for 30 days and can be restored with ``trash_restore_project`` using the project's document id from the delete response or ``trash_list``. After 30 days it is permanently removed. Active trainings on the project are cancelled.
Enqueue an async fork of a public Universe project into your workspace. Provide either a Universe `url` or `source_project`. Returns the platform's 202 payload verbatim — at minimum `{ taskId, url }`, where `url` points at the async-task polling endpoint. Poll completion with `async_tasks_get(task_id=taskId)` every 5 seconds until `status` is terminal (`completed` or `failed`). Processing may take up to 30 seconds to start.
Enqueue an async rebalance of a project's train/valid/test splits. Use this to fix a starved or empty split — an empty test split blocks training, and this is the only way to move images between splits after upload. `train`, `valid` and `test` are relative weights, not percentages: they do not have to sum to 100, and each must be a whole number (70, not 70.5). `mode="rebalance"` moves the fewest images needed to reach the ratios; `mode="shuffle"` reassigns every image. Returns the platform's 202 payload verbatim — at minimum `{ taskId, url }`, where `url` points at the async-task polling endpoint. Poll completion with `async_tasks_get(task_id=taskId)` every 5 seconds until `status` is terminal (`completed` or `failed`).
Get the stable live endpoint state for a project, with `workspaceDetectionDefault` and `openAiDetectionAvailability`. Use the returned `workspaceDetectionDefault` for new non-COCO object-detection Workflow steps and object-detection catalog labeling with no explicit model choice. Free/trial workspaces: Gemini 4 Argon (`gemini-4-argon-boxes`) for Workflow detection and catalog labeling; new endpoints GPT-6.1 Sol (`{type: "sol", classes}`). Paid workspaces or unknown usage: Gemini 4 Argon (`gemini-4-argon-boxes`) for Workflow detection and catalog labeling; new endpoints GPT-6 Astra (`{type: "astra", classes}`). If `workspaceDetectionDefault` is absent, use the paid default. The Auto Label model and the endpoint model are separate: name an endpoint by its endpoint model, never by the Auto Label one. Never infer the tier from user messages. Explicit supported choices and existing saved models take precedence. The returned `openAiDetectionAvailability` applies to OpenAI blocks and endpoints. When it is `available` or absent, follow the workspace detection default. A `managed-key-denied` or `region-unavailable` restriction does not establish another provider's availability: retain a non-OpenAI default only when its own access and deployment policies permit it. When no permitted VLM default is available, use the native SAM 3 fallback without another selection question. Never switch providers, credentials or global routes to evade plan, workspace-key or residency restrictions.
Create or prepare a stable Project Deployment. Configure this optional endpoint only when the requested task needs a stable serving endpoint or active learning. A new Project's detection default can only be read once the Project exists. For a new object-detection Project outside COCO with no explicit model choice, call this without `model` or Active Learning, read the returned `workspaceDetectionDefault` and `openAiDetectionAvailability`, then call project_deployment_set_model with `{type: workspaceDetectionDefault.objectDetectionEndpoint.type, classes}` (the classes to detect) as project_deployment_get describes, then project_deployment_enable_active_learning if wanted. Active Learning needs a model on the endpoint.
Change which model a Project's hosted endpoint serves without changing its stable inference path. Creates the endpoint if necessary. Configure this optional endpoint only when the requested task needs a stable serving endpoint or active learning. Ordinary model testing and Auto Label samples use a standalone Workflow and need no endpoint configuration. Never replace a configured serving model or saved prompt unless the user explicitly requests that persistent change. Training completion, Auto Label setup, Adjust feedback, and trying a preview do not authorize replacement. This saves the configuration, so do not describe it as temporary. Never use this tool for temporary classes or confidence changes. Active Learning settings are preserved. If the user explicitly requests Sol or Astra and project_deployment_get's `openAiDetectionAvailability` is `managed-key-denied`, explain that its managed-key access is unavailable in this workspace and offer SAM 3 or resolving that access. If it is `region-unavailable`, explain that OpenAI detection is unavailable in the EU deployment and offer SAM 3; do not suggest upgrading the plan or adding a provider key as a residency workaround. Do not configure a new Sol or Astra detection endpoint or suggest a global provider route in that case. For either restriction, do not configure a substitute without their agreement or claim the requested detector ran. Never bypass provider-access controls. Leave existing configured endpoints, COCO RF-DETR, other task defaults, and Auto Label's separate selection policy unchanged.
Run inference through the project's stable live endpoint.
Enable Active Learning for a Project Deployment.
Pause Active Learning collection for a Project Deployment.
Configure how a Project Deployment collects Active Learning data.
List Active Learning review queues fed by production inference.
Prepare a signed URL for uploading a zip of images, annotations or MP4/MOV videos. Use image_upload_files when the host supplies the selected files in its files input. If you would have to invent download_url or file_id, use this signed-URL flow instead when the client can ZIP and PUT the files. Use this fallback only when host-assisted file transfer is unavailable or cannot handle the selected files, and the client can zip them and HTTP PUT to the signed URL. If its sandbox cannot reach storage, do not keep retrying the PUT; use host-assisted transfer or direct the user to the web uploader. This tool does not read, zip, or upload files. To mirror images from cloud storage (S3/GCS), use the datasource tools. Returns a signed upload URL, task ID, and client-side instructions. File bytes are transferred by the client in this flow. Requires the project slug, plus optional split, batch name, tags and annotation_overwrite. Local file paths are used by the client after this tool returns, not passed here. Remaining steps after this returns (detailed in the response instructions): 1. Zip the images and any annotation files (even one image → zip). Paths inside the zip set splits: train/, valid/ and test/ folders override the split argument per image. 2. HTTP PUT the zip to signedUrl. 3. Poll image_upload_status(task_id) every few seconds until completed or failed. Videos in ZIPs require a video-only project (such as Action Recognition). Poll video_upload_status for every result.videoIds entry after ZIP processing; use the final videoId from each uploaded response. result.videoIds stops at 100 IDs; if result.videosStaged exceeds that list length or failedChunks > 0, counts may be incomplete. Find remaining videos with images_search(project_id, media_types=["video"]), poll video_upload_status for unverified videos, and report a partial import if they cannot all be accounted for. Image projects skip videos, and video-only projects skip images. Inspect warnings and errors, even when the ZIP task completed. For one raw video up to 3 GB, use video_upload. Annotation files in the zip are imported with the same parser as the web uploader: COCO JSON (e.g. one _annotations.coco.json per split folder), YOLO TXT (with data.yaml or classes.txt for class names), Pascal VOC XML, CreateML JSON, CSV, and the other formats it accepts. Annotations are matched to images by file name. In classification projects, an image's parent folder is its class (cat/img1.jpg). Images with annotations are added straight to the Dataset, so there is no annotation job to accept (with annotation review turned on for the workspace, they wait in a review job instead). Images without annotations land in a batch: label them later with annotations_save and pass add_to_dataset=true there, which is what makes them usable for training. An image already in the project counts as a duplicate and is not stored again, but its annotation from the zip is still saved. An image that already has an annotation in this project's annotation group (for example from another project in the workspace that uses the same group) keeps it and is listed in annotationErrors, unless annotation_overwrite is true. Up to 2 GB / 10k files. Signed URL expires in 1 hour.
Upload images or MP4/MOV videos into a project through the host's file transfer bridge. Use this when the host supplies the selected files in the files input, including when it exposes local paths and transfers them for you. If you would have to invent download_url or file_id, use image_upload or video_upload instead when the client can PUT the bytes. Do not invent file references or put file bytes in tool arguments. The Roboflow server downloads the supplied files and uploads them as one zip. No terminal ZIP or PUT is needed, including when the code sandbox cannot reach storage. Fall back to image_upload only when the bridge is unavailable or cannot handle the selected files, and the client can zip and HTTP PUT them to storage. An authentication, validation, or server error does not by itself mean the bridge is unavailable. For image projects, pass images plus any annotation files, matched to images by file name (COCO JSON, YOLO TXT with data.yaml or classes.txt, Pascal VOC XML, CreateML JSON, CSV), or one zip on its own. A zip keeps its folders, so train/, valid/ and test/ folders set each media file's split. Up to 100 files and 1 GB total per call; send larger file counts as one zip within that limit. For video-only projects (such as Action Recognition), pass MP4/MOV videos or a zip containing them. Videos remain native videos, not extracted frames. Image projects skip videos; video-only projects skip images, with warnings. Do not treat a mixed batch as fully imported without checking those warnings. When the host cannot transfer videos, use video_upload for a raw video or image_upload for a ZIP, only if the client can PUT to storage. Returns a taskId once the files are uploaded. Poll image_upload_status(task_id) every few seconds until it is completed or failed. Inspect uploadErrors, annotationErrors and warnings. For videos, ZIP completion only means staging: then poll video_upload_status for every result.videoIds entry until uploaded or failed. Use the final videoId from each uploaded response (deduplication can change it). result.videoIds stops at 100 IDs while result.videosStaged counts videos from successful chunks. If videosStaged exceeds the returned list length or failedChunks > 0, counts may be incomplete. Find remaining videos with images_search(project_id, media_types=["video"]), poll video_upload_status for unverified videos, and report a partial import if they cannot all be accounted for. Images with annotations go straight into the Dataset; images without them land in a batch to label with annotations_save.
Check the status of an image or video ZIP upload task. Use after the zip has been PUT to the signed URL (image_upload step 2), or after image_upload_files returns. Poll every 3–5 seconds until status is completed or failed. Returns status (created, running, completed or failed), progress, and, once finished, a result with uploaded, duplicates and annotated image counts, videosStaged and videoIds, plus uploadErrors, annotationErrors and warnings (for example annotations that matched no image, or ignored files). Error lists stop at 100 entries. A completed ZIP task does not mean its videos finished ingesting: poll video_upload_status for every result.videoIds entry until uploaded or failed, even when the ZIP task failed after staging some videos. Use the final videoId from each uploaded response. result.videoIds stops at 100 IDs, while result.videosStaged counts videos from successful chunks. If videosStaged exceeds the returned list length or failedChunks > 0, counts may be incomplete. Find remaining videos with images_search(project_id, media_types=["video"]), poll video_upload_status for unverified videos, and report a partial import if they cannot all be accounted for. Check errors and warnings before reporting success; image projects skip videos and video-only projects skip images. Status stays "created" until the first chunk finishes; progress gets a total as soon as processing starts. If the task is still "created" with no progress 10 minutes after a successful PUT, the zip was not processed (for example it held no supported media files): stop polling, fix the input files and retry using the upload selection rules below. The zip is processed in chunks. If any chunk fails, status is "failed", failedChunks is above 0, and uploadErrors holds an entry whose path names the chunk (e.g. "chunk-0"). That chunk's images may already be stored without their annotations, and its counts are missing from the totals. Re-uploading the same files is safe and repairs this: stored images come back as duplicates and their missing annotations are saved. Images whose annotations were saved the first time are then listed in annotationErrors as "Image was already annotated", which is expected. For retries, use image_upload_files when the host supplies fresh selected files in its files input. If you would have to invent download_url or file_id, use the signed-URL fallback instead. Use image_upload only when host-assisted transfer is unavailable or cannot handle those files, and the client can ZIP and PUT to storage. A failed import does not by itself mean the file transfer bridge is unavailable. If sandbox networking blocks storage, use host-assisted transfer or the web uploader instead of retrying signed PUTs.
Add existing workspace Asset Library images or videos to a project (async). Use for sources already in the workspace: media_upload_finalize results (`sourceId` / `videoAssetId`), cloud-storage datasource mirrors, or images in another project. A newly uploaded video is addable only after ingestion; until then this returns 404 "Image not found in workspace", so retry later. If it still 404s after a few minutes, ingestion failed or merged it: tell the user. Find ids or build the filter with images_workspace_search. To upload new local images, prefer image_upload_files when the host can supply them in its files input; if you would have to invent download_url or file_id, use image_upload if the client can ZIP and PUT to storage. For videos, prefer image_upload_files only for video-only projects when the host can supply the selected files in its files input. If you would have to invent download_url or file_id, use the signed-URL fallback. For other project types, use video_upload; also use it when host transfer cannot handle the video. video_upload requires a client that can PUT bytes to the signed URL. If storage is unreachable, use the web uploader. The source stays owned by the workspace: the project gets an association, not a copy. Added sources land in one new batch (`batchId`). Images and videos cannot be added together; the task fails on a mix. API keys and OAuth tokens restricted to folders get a 403. Returns `{ taskId, projectId, selectionMode, imageCount?, url, ... }`. Poll async_tasks_get(task_id) until status is `completed` or `failed`. A completed result has `batchId` (null when nothing new was added), `imagesLinked`, `imagesSkipped` (already in the project, removed, or filtered out by media type) and `annotationsCopied`. Added sources are not in the Dataset yet, so training cannot use them. Sources without labels: annotate them with add_to_dataset=true on annotations_save (images) or video_segments_annotate (Action Recognition videos). Sources that arrive labeled (copy_annotations_from_project_id, or labels the project already shares): create a job from `batchId` with annotation_jobs_create, then annotation_jobs_accept_into_dataset.
Prepare a signed URL for uploading one local video (MP4 or MOV) into a project. Use this to put a video into a project, for example an Action Recognition project you will label with video_segments_annotate. This tool does not read or upload local files: the client HTTP PUTs the bytes to the returned signed URL. Prefer image_upload_files for MP4/MOV files in video-only projects when the host supplies them in the files input, including local paths when the host transfers them. If you would have to invent download_url or file_id, use video_upload. For other project types, use video_upload because ZIP imports skip videos. Use this signed-URL fallback when the host cannot transfer the selected video or it exceeds the file transfer tool's 1 GB limit, and the client can read and PUT the file. If sandbox networking blocks storage, use host-assisted transfer for video-only projects or the web uploader instead of repeating failed PUTs. Returns signedUrl, requiredHeaders, videoId, and client-side instructions. Remaining steps after this returns (detailed in the response instructions): 1. HTTP PUT the raw video file to signedUrl with every requiredHeaders entry plus a Content-Type header. 2. Poll video_upload_status(video_id) every few seconds until status is "uploaded" or "failed". Use the videoId from the "uploaded" response. Re-uploading identical bytes creates no new video. It updates the existing one instead: its split and metadata change to this call's values and the tags are added. Up to 3 GB per video. Signed URL expires in 1 hour.
Check ingestion of a raw video upload or a video staged from a ZIP. Use after the raw video PUT (video_upload step 1), or for each videoId returned by image_upload_status after image_upload_files or image_upload. Poll every 3-5 seconds while status is "pending"; "uploaded" and "failed" are terminal, and "failed" includes a message. When status is "uploaded", the response videoId is the final video ID (the canonical Source ID). Pass that videoId to video_segments_annotate. It can differ from the id you polled with: when an identical video already existed, the upload is deduplicated, duplicate is true, and videoId names the existing video. That video takes the split and metadata of the new upload, gains its tags, and resolvedBatch is null. Otherwise resolvedBatch names the batch the video joined.
Update metadata and tags on a single image. Metadata and tags can be useful to find images later in the platform. Common metadata include photo location, camera, date. Provide at least one of: metadata, remove_metadata, add_tags, remove_tags. The same key cannot appear in both metadata and remove_metadata; the same tag cannot appear in both add_tags and remove_tags. Returns { success: true } on success.
Batch-update metadata and tags on multiple images (async). Each item in updates must contain an 'imageId' and at least one mutation bucket. Same conflict rules as the single-image endpoint. Returns { taskId, url } with status 202. Poll completion via async_tasks_get with the returned taskId.
Search images across the entire workspace using RoboQL. The workspace is determined automatically from the API key — no workspace or project parameter is needed. Just provide a query. Use RoboQL syntax to filter by project, Dataset membership, split, class, tag, metadata, and more; combine filters with AND, OR, NOT and parentheses. Quote filter values that contain wildcards or spaces, for example ``filename:"frame_*"``. An unquoted wildcard is invalid RoboQL. This is the tool for split filters and other RoboQL queries scoped to one project: add project:<slug>. Request the `url` field when you need a direct image URL. Returns results with a continuationToken for pagination. To put results into a project, pass their ids (or the same structured query and media_types) to images_add_to_project.
Search images in one project by what they show, with optional filters. query is semantic search: results are ranked by how well they match the text, but the query does not narrow them, so total does not change with it. Narrow results with tag, class_name, in_dataset, batch, batch_id, annotation_job and annotation_job_id. There is no split filter here. For RoboQL (split:, metadata:, filename:, NOT, OR, and so on), use images_workspace_search with project:<slug> in the query, e.g. 'project:my-project split:valid'. Returns { offset, total, results }.
Search images inside a public Universe dataset given its URL. Accepts a full Universe dataset URL and derives the workspace and project slugs from it before searching the dataset's images.
Analyze an image or short video with a vision model to understand its contents. Returns a structured analysis: a summary, the distinct objects present with approximate counts, the best-fitting CV task (detection, segmentation, classification, OCR, tracking...), candidate class names, whether those classes fall within the 80 COCO classes (drives model-family selection), motion notes for video, and workflow recommendations. Pass any public HTTPS URL directly — image results from images_search, images_workspace_search, or universe_dataset_images_search already include a usable `url` field. For a local file on the user's machine, call media_upload first and analyze the URL it produces. This is a stateless one-shot primitive: nothing is recorded in a conversation. Costs workspace credits (one vision-model call per invocation). Storage allows videos up to 100 MB, but ANALYSIS is capped at ~15 MB by the vision gateway's url fetcher; trim longer footage before analyzing.
Prepare a local image or video for analysis with media_analyze. Returns a short-lived signed upload URL plus step-by-step instructions; the upload itself completes client-side (the MCP server never receives file bytes). After the PUT, call media_upload_finalize to validate the bytes. For images and small videos it returns a durable `url` to pass straight to media_analyze; for videos over the analysis budget it returns `needsTrim: true` with a `videoAssetId`, and you call media_trim to get the analyzable clip url. Only needed for files on the user's machine; media already reachable by an HTTPS URL (including Roboflow-hosted images) can go straight to media_analyze. To put a video into a project (e.g. for annotation), prefer image_upload_files only for video-only projects when the host supplies it in the files input. If you would have to invent download_url or file_id, use video_upload. For other project types, use video_upload because ZIP imports skip videos. Also use video_upload when host transfer cannot handle the video. It requires a client that can PUT bytes to the signed URL; if storage is unreachable, use the web uploader. Finalized images and videos are saved into the workspace Asset Library (reusable across the workspace; re-uploading identical bytes reuses the existing asset instead of duplicating it). The analyzable copy ends up on a public CDN at an unguessable URL. To put a finalized image into a project, pass its `sourceId` to images_add_to_project.
Cut a clip from an Asset Library video and get an analyzable public url. Use after media_upload_finalize returns `needsTrim: true`. The simplest call is media_trim(video_asset_id) with no window: the server cuts the longest clip the ~15 MB analysis budget allows from the start (typically up to ~95 seconds; often the entire video, since long windows are re-encoded, downscaled to at most 1280px, to fit). Pass start_seconds/duration_seconds only when your user cares about a specific segment. The response tells you exactly what happened: `clipSeconds` (what was actually cut), `requestedSeconds`, `clamped: true` when the server shrank the window, plus authoritative `videoDurationSeconds` and `maxClipSeconds` from the server-side probe. Report the real clipSeconds to your user; to cover the rest of a long video, cut the next clip at start_seconds + clipSeconds and repeat. Only the published clip is re-encoded; the full-quality video stays untouched in the Asset Library.
Validate a staged upload (from media_upload) and publish it. Checks the uploaded bytes match the declared media type and size limits. Images become workspace Asset Library assets (the response includes their `sourceId`) and return a durable public `url` to pass to media_analyze. Videos always become Asset Library records (`videoAssetId`). Small videos also return a durable `url` right away (`needsTrim: false`). Videos over the analysis budget return `needsTrim: true`: call media_trim(video_asset_id) with no window to get the maximal analyzable clip, and read the authoritative numbers from its response. If you passed duration_seconds here, the response also includes `maxClipSeconds` and `wholeVideoFits` (true when one clip covers the entire video, so there is nothing to ask the user). Ask YOUR USER which segment matters only when the video is longer than one clip can cover. The full video stays in the Asset Library either way. The staged object is removed whether validation passes or fails, so a failed finalize means starting over with a fresh media_upload. To add the finalized asset to a project, pass its `sourceId` or `videoAssetId` to images_add_to_project. A new video becomes a Source only after ingestion finishes (seconds to minutes); until then images_add_to_project returns 404 "Image not found in workspace". Retry later, or look up its final id with images_workspace_search(media_types=['video']), since ingestion can merge identical bytes into an existing video. If it still 404s after a few minutes, ingestion failed or merged it: tell the user instead of retrying.
Annotate one Action Recognition video Source with a complete video-coco document. Upload the video with image_upload_files when the host supplies it in the files input; if you would have to invent download_url or file_id, use video_upload if the client can PUT the bytes to the signed URL. For image_upload_files, first poll image_upload_status until ZIP processing completes, then poll video_upload_status for each returned video ID. Use the final videoId once status is "uploaded" (it can differ from the staged ID after deduplication). The ZIP status videoIds list stops at 100 IDs; if videosStaged exceeds the returned list length or failedChunks > 0, counts may be incomplete. Find remaining videos with images_search(project_id, media_types=["video"]), poll video_upload_status for unverified videos, and report a partial import if they cannot all be accounted for. Preserve the video's native PTS, frame indices, and rational time base. The API creates unknown classes unless the project locks them. It controls overwrite, split, and Dataset membership. No training starts.
Save an annotation for an existing image. By default this only stores the annotation: it does not change whether the image belongs to the project Dataset. Pass add_to_dataset=true to also add the image to the Dataset. That membership is what makes the image count toward a dataset version, so an image that is uploaded and annotated but never added to the Dataset will show up as 0 images in versions_generate. Set prediction_routing to ``review`` to request an automatic move from the target-project batch into a Review job only when the image has target-project batch membership and no target-project annotation-job membership. Set it to ``unassigned`` to suppress that move and preserve existing batch, annotation-job, and Dataset memberships. Prediction uploads never add Dataset membership, even when add_to_dataset is true, and existing Dataset membership is preserved. Neither value guarantees movement to a named queue. Saving onto an image that already has annotations fails with a 409 conflict unless you pass overwrite=true, which replaces the existing annotation. Classification projects never hit that conflict: their saves already overwrite.
List the foundation models available for hosted auto-labeling in this workspace. Returns ``{models: [...]}``. Each entry's ``id`` (e.g. ``gpt-6-astra-boxes``, ``sam3-rle``, ``gemini-3-8-flash-boxes``) is a valid ``model`` value for ``autolabel_start`` with ``model_type='foundational'``. Entries carry ``guidance`` on when to prefer each model, ``projectTypes`` / ``excludedProjectTypes`` they support, ``ontologyFormat`` (``promptMap``: prompts are sent to the model; ``classes``: only class names are used), ``creditsPerImage``, ``isDefault`` (the recommended starting point when the project type supports it; otherwise the first entry that does), and ``available`` with an ``unavailableReason`` when the workspace's plan blocks a model. Call this before ``autolabel_start`` to pick a model instead of assuming which ones exist. When the user has not chosen a model, follow up with ``autolabel_preview`` to compare the candidates on one sample image before committing to a job.
Preview one image with a foundation model to judge it before starting an auto-label job. Previews are for comparing candidate models on a few sample images. They create no job and spend no credits, but they are rate limited per workspace (the limit is shared with the Roboflow app), and past the limit the call fails with a 429 that says when to try again. Labeling a batch must go through autolabel_start: do not preview images one at a time and keep the predictions as labels. Use this as the model-selection loop when the user has not picked a model: 1. Call autolabel_models_list and order the candidates (the default first, then whatever the guidance recommends for the ontology at hand). 2. Pick one representative image from the batch (e.g. from the batch or image listing tools) and preview it with the first candidate. 3. Judge the summary: entries in classesWithNoDetections, a suspiciously low totalDetections, or blockErrors mean the model likely will not label this data well. Preview the next candidate and compare. 4. Start the real job with the winner via autolabel_start, using the same ontology. Returns ``{model, summary, predictions, blockErrors?}``; summary.byClass carries per-class counts and max confidence, and predictions are trimmed to class, confidence, and box geometry (polygon and mask geometry is dropped to keep responses small).
Start a hosted auto-label job over a batch of images. Call ``autolabel_models_list`` first to pick a foundation model; its entry ids (e.g. 'gpt-6-astra-boxes', the default for object detection) are valid ``model`` values. If the user has not chosen a model, run ``autolabel_preview`` on a sample image per candidate and start the job with the best one. Returns ``{jobId, annotationJobId, message}``. Poll progress with ``autolabel_job_get`` using the returned ``jobId``.
Get per-subjob status and progress for an auto-label job. Returns status, model/project type, image counts, subjob progress, ontology, confidence thresholds, and the linked annotation job id.
Summarize a project's Annotate board: Unassigned, Annotating, Review, and Dataset. Proxies GET /:workspace/:project/annotation-board. Returns column counts and progress, plus per-labeler and per-reviewer rollups. Use annotation_jobs_list and annotation_batches_admin_list when you need more pages of items.
List upload batches in a project.
Get details about one upload batch.
List annotation-board batches with cursor pagination.
Get details about one annotation-board batch.
List image IDs in a batch with cursor pagination.
Move selected images from one batch into a new batch.
Move all images from source batches into a target batch and remove the emptied sources.
Delete a batch. By default its images move to unassigned and remain accessible.
List annotation jobs and return a continuation token when more exist.
Get details about one annotation job.
List image IDs assigned to a job with cursor pagination.
Create a job and move images from a batch into it.
Create a job from selected images, removing their prior assignment or Dataset membership.
Move images into an existing job and reconcile assignment and Dataset counters.
Update exactly one of a job's labeler, reviewer, or instructions.
Advance a labeling job into review.
Move a review job back to labeling, optionally with a new labeler.
Set the explicit review status for one image in a job.
Set a status for every job image matching the supplied current status.
Finalize selected job images into the Dataset and assign splits.
Remove a job while moving its images to an unassigned batch so they remain accessible.
Delete the project's annotation data for every image assigned to a job.
Create a new dataset version with optional preprocessing and augmentation. Preprocessing and augmentation choices are user decisions: confirm the desired options with the user before generating rather than assuming defaults. Pass each option in the shape this tool's schema shows. The platform rejects its internal saved shape (``{"enabled": true, ...}``, ``remap.labels``, ``crop.percent``) and the step lists that trainings_create recipes use. Generation continues after this tool returns and can take several minutes. While ``generating`` is true, poll versions_get roughly once a minute before starting training or requesting an export. The export request is not queued while generation is in progress. Returns the version number, image count, split sizes, and readiness fields.
Get info about a dataset version including splits and its trainings. Returns version details with id, name, images, splits, preprocessing, augmentation, and a ``trainings`` summary (one entry per training on the version: ``trainingId``, ``status``, ``modelType``, ``modelGroup``, ``modelIds``). Use trainings_get for a single run's detail and metrics. Readiness fields report generation state for callers that need to poll: ``generating`` is true only while generation looks actively in progress, and ``ready`` is true once generation is not active AND at least one train/valid/test split count is present. Generation usually takes several minutes and can take up to about an hour on large datasets, with ``progress`` stuck at 0 or null for most of that wait: that is normal, not stuck. Poll this tool roughly once a minute until ``ready`` is true. Trainability floors (min images per split, labels, NAS mins) are enforced by the platform train endpoint; if ``ready`` is false only because splits are empty/insufficient, waiting will not help. Call trainings_create and surface that error.
Delete a dataset version, moving it to the workspace Trash. This is a soft delete: the version stays in the Trash for 30 days and can be restored with ``trash_restore_version`` using the version's document id and ``parent_id`` set to the parent project's document id (both are in the delete response or ``trash_list``). After 30 days it is permanently removed.
Check or trigger a dataset export for a version. Generation must finish first: use versions_get to check ``generating`` and poll roughly once a minute while it is true. An export request made during generation is rejected and does not queue the export.
List trained models associated with a project. Returns ``{models, total, returned, limit, offset, truncated}``. Each row carries `metrics`, and (for NAS children) `nasFamily` and `group`, plus a derived `recommended` flag when the model is the recommended pick for any (metric, hardware) bucket on its parent version. `metrics` is sparse and its keys depend on the run. An ordinary training carries accuracy only, e.g. {map50, precision, recall, f1}. `latency` and `paretoOptimalFor` come from NAS mining, so they appear on NAS children and not on ordinary trainings; `metrics` may also be null. Do not assume a key is present - read what is there. Two shapes of NAS child are in the data. Newer runs report `latency` as a map keyed by target hardware (e.g. {"AI1": 6.69, "T4": 1.98}) and `paretoOptimalFor` entries as "<hardware>:<metric>" (e.g. "T4:map_50_95"). Older runs report a scalar `latency` with a sibling `metrics.hardware` (e.g. "gpu") and bare-metric `paretoOptimalFor` entries (e.g. "map_50"). Branch on the type of `latency` rather than indexing it. `recommended` is the flattened union of the platform's per-hardware winners, so more than one row in a group carries it and it cannot tell you which hardware a child won; `paretoOptimalFor` is frontier membership, not the recommendation. The authoritative map, `recommendedByHardware`, exists only on legacy version-based summaries and is absent from modern MMPV runs. NAS children with `nasFamily: "baseline"` are stock RF-DETR models trained on the same data; they carry no `paretoOptimalFor` and are never `recommended`. A project with NAS runs can have hundreds of models, so the result is always bounded: filter with `version_number` and/or `group=<modelGroup>` (the canonical "list NAS models per run" path), and page with `limit`/`offset`. `truncated` is true when more rows remain past the page.
Get details for a trained model in the current workspace.
Run hosted inference on an image using a trained model. The model id is passed straight to the inference server, which resolves the model and its task from the id — no project-type derivation is needed. Returns JSON predictions only. For visualized/annotated images, run a Workflow with a visualization block instead.
Describe the tuning surface for a model type and get a ready-to-submit train recipe. Returns two things: - ``schema``: the valid tuning knobs for this model on this version, namely manifest hyperparameters with hard bounds (``valid``) and advisory ranges (``advice.low``/``advice.high``) for a deliberate, hypothesis-driven change. A descriptor's ``advice.default`` is the tuned value the server applies when you omit the key, so a sparse recipe is the good default; a descriptor with NO ``advice.default`` is one only the trainer can resolve (it derives the value from the dataset at train time), so leave those out unless you specifically intend to override the derivation. Also included: the task-supported online augmentation steps with their field contracts, the supported online preprocessing steps, and input/resolution rules. - ``template``: a ready-to-submit ``trainRecipe`` for this model type. Edit the knobs you want to change, then pass the whole dict as ``train_recipe`` to trainings_create. An unknown ``model_type`` fails with a 404 whose error body lists the valid model types for the project's task.
Create a training on a dataset version. IMPORTANT: A dataset version must exist before training. Use the versions_generate tool first to create one with the desired preprocessing and augmentation settings. A modern (MMPV) version may own MANY trainings — concurrent and repeated runs are allowed. Legacy single-model-per-version (SMPV) versions already hold their one model and reject a second training with a 409; generate a fresh version to train more models. To inspect a version's trainings, use trainings_list; to monitor a specific run, use trainings_get with the returned training_id. For Action Recognition, pass model_type='cosmos3-edge'. Its video-coco export is prepared by this call. The returned trainingId identifies a background v2 run; poll trainings_get with it until the run finishes. A train_recipe is optional and is sent only when you supply one. MODEL CHOICE: for object detection and instance segmentation, prefer a NAS parent over a single named architecture: searching the architecture space against this dataset usually beats hand-tuning one. See the model_type description for ids and prerequisites. To customize hyperparameters or online augmentation, call trainings_describe_recipe FIRST, edit its ``template`` (set ``template["hyperparameters"]``; add augmentation steps as ``{name, params: {...}}`` dicts), and pass the whole dict as train_recipe. Recipe hyperparameters are sparse: keys you leave out keep their server-side defaults, which are the tuned values, so omitting a key is the right default, not a missed opportunity. Set a knob when you have a specific reason to move it, not to explore. Recipe training requires platform recipe access and an enabled runtime; trainings_describe_recipe reports their availability. COMPARING ARCHITECTURES: launch one trainings_create per candidate (MMPV versions allow many concurrent trainings) and keep each returned trainingId. Include a NAS parent as one of the candidates whenever its prerequisites are met, e.g. 'rfdetr-medium' vs 'yolo26m' vs 'rfdetr-nas-parent'. A NAS arm returns a frontier of models rather than one. Resolve it with trainings_list -> modelGroup -> models_list(group=<modelGroup>), whose docstring describes the per-child fields; use trainings_list rather than trainings_get, which inlines every child and defeats the paging. Which child represents that arm depends on the question being asked, and the obvious reading of the `recommended` flag is wrong - read the training-and-evaluation skill before comparing arms or deploying. This tool checks that the dataset version has finished generating and that the required export is ready before starting, and waits up to about 20 seconds for the export. If either is still pending it does NOT start a training: it returns status 'waiting_for_version' or 'waiting_for_export' with training_started false, no trainingId, the progress, and retry_after_seconds. That is expected, not a failure: call trainings_create again with the same arguments after that delay, and keep retrying until it returns a trainingId. Version generation can take up to about an hour on large datasets and reports 0 progress for most of it. Training runs in the background on Roboflow servers.
Get the recipe for uploading locally trained model weights to Roboflow. This tool never uploads anything. Weights packaging must run on the machine that has the checkpoint (it reads the weights file and needs torch), and this MCP server cannot read the user's filesystem. Calling it returns the client-side recipe: how to run the upload with the Roboflow Python SDK on the machine where the weights live. Pass whatever arguments you already know; the response names the matching upload mode and echoes them back for the SDK call. Do not infer the target project, version, or model name from the checkpoint; those come from the user.
List the trainings on a dataset version. A version may own many trainings. Returns one entry per run: ``{ trainingId, status, createdAt, modelType, modelGroup, modelIds }``. ``createdAt`` is when the run was launched (ISO 8601 UTC), or null if unknown. Entries are sorted oldest-to-newest by ``createdAt``. Statuses are surfaced verbatim (e.g. 'finished', 'failed', 'cancelled', 'stopped', 'running'). Pick a ``trainingId`` and pass it to trainings_get, trainings_cancel, or trainings_stop.
Get a training's status, produced models, and metrics. With ``training_id``, returns that run: ``{ trainingId, status, createdAt, modelType, modelGroup, modelCount, models: [ { modelId, nasFamily, metrics, recommended }, ... ], recommendedByHardware?, mining?, epochs?: [ { epoch, ts_ms, map50?, map50_95?, precision?, recall?, f1?, accuracy?, miou?, latency?, modelKey? }, ... ] }``. ``createdAt`` is when the run was launched (ISO 8601 UTC), or null if unknown. Statuses are surfaced verbatim: 'failed', 'cancelled', and 'stopped' are distinct. Without ``training_id``, returns the version's sole run. A version with several trainings returns 409 ``MULTIPLE_TRAININGS``; use trainings_list to choose a run and pass its ``training_id``. Set ``include_epochs=True`` to include per-epoch telemetry in ``epochs``. Entries have flat metric fields. ``map50``, ``map50_95``, ``precision``, ``recall``, ``f1``, ``accuracy``, and ``miou`` are percentages (0 to 100). ``latency`` is a number or an object of numbers; ``ts_ms`` is a Unix timestamp in milliseconds. NAS runs with several curves include ``modelKey`` on each entry: group by ``modelKey`` before comparing or plotting epochs so different curves stay separate. The API rejects this option for legacy single-model-per-version trainings. For headline metrics (mAP/precision/recall) on a specific model, use model_evals_list to find the version's evaluations and then model_evals_get and its siblings. Those tools require the ``model-eval:read`` scope, so eval lookup is deliberately kept out of this tool — monitoring a run only needs ``version:read``. For full per-model metadata on a NAS run, call models_list with the returned modelGroup.
Cancel an in-flight training run. Works for any architecture. For NAS runs the underlying handler accepts the ``mining`` status — same call cancels mining or training phases.
Request an early stop on an in-flight training run. Distinct from cancel: the run finishes the current phase gracefully (mining or training) instead of terminating immediately.
Delete a training run, moving it to the workspace Trash. This is a soft delete: the training stays in the Trash for 30 days and can be restored with ``trash_restore_training`` using the training id. After 30 days it is permanently removed. Deleting may repoint or remove the ``{project}/{version}`` serving alias; the response reports the alias action taken.
Star or unstar a NAS-trained model. NAS-only by design — the server rejects non-NAS modelTypes with a ``MODEL_NOT_NAS`` error. Starring triggers TRT compilation for the model's recommended hardware so the model becomes deployable as an edge target.
Compare models trained on or uploaded to one dataset version. Returns the project, version, selected frontier metric, available metrics, and one compact record per model. Each record includes evaluation metrics, median latency, exclusion reason, and server-computed frontier membership. Frontier membership indicates a speed/accuracy tradeoff, not a model recommendation or selection. This tool is read-only and starts no jobs.
List model evaluations in the current workspace. Returns ``{evals: [...]}`` where each entry has evalId, status, project (URL slug), versionId, modelId, modelUrl, and createdAt. Use ``model_evals_get`` for the headline ``summary`` (mAP/precision/recall) on a specific eval. Two model identifiers are returned and they are NOT interchangeable: ``modelId`` is the eval's internal id (the ``model_id`` filter key here); ``modelUrl`` is the resolvable public id that ``models_get`` / ``models_infer`` accept and that joins to ``models_list[].url`` and ``trainings_get`` results. Filters combine: ``project_id`` + ``version_number`` returns the evals of that project version, ``model_id`` + ``version_number`` the evals of that model on that version. The version is matched within the newest 200 evals of the project or model, the most the platform returns per call.
Get the top-level summary for a single model evaluation. Returns the eval metadata plus a ``summary`` of mAP / precision / recall on done evals, and an ``app_url`` deep link into the UI panel. The ``modelUrl`` field is the resolvable public model id (feed it to ``models_get`` / ``models_infer``); ``modelId`` is the eval's internal id. The ``model_evals_get_*`` result tools only work once ``status`` is ``done``; while it is ``pending`` or ``running``, poll this tool first.
Get per-split mAP results for an eval. Returns ``{splits: {train, valid, test}}`` where each split has overall ``map50`` / ``map50_95`` / ``map75``, ``byObjectSize`` (small/medium/large), and ``perClass`` breakdowns.
Get the precision/recall/F1 confidence sweep for an eval. For each split returns ``perThreshold`` (metrics keyed by threshold like ``"0.20"``), the ``optimalThreshold`` and ``optimalMetrics``, and ``perClass`` sweeps.
Get per-class performance metrics for a single split. Returns ``{split, classes: [{className, map50, map50_95, map75, precision, recall, f1, optimalThreshold}, ...]}``.
Get the confusion matrix for an eval. Returns ``{split, confidenceThreshold, classes, matrix}`` where ``matrix[actual][predicted]`` is the count.
Get UMAP + HDBSCAN clustering of image embeddings for an eval. Returns ``{clustering, preprocessing, clusters: [...]}`` — useful for finding pockets of poor-performing images. Each cluster carries ``numImages``, ``splitDistribution``, F1 stats, and sample image refs.
Get per-image prediction stats for an eval (paginated). Returns ``{split, confidenceThreshold, totalImages, offset, limit, images: [...]}``. Each image carries TP/FP/FN counts, precision, recall, F1, the assigned cluster, and a per-class confusion list.
Get the LLM-generated recommendations for an eval, if available. Returns ``{generated: false}`` until the recommendations job has run. When ready, returns ``{generated: true, generatedAt, recommendations: {summary, items}}``.
List saved workflows in the current workspace. Returns up to ``limit`` workflows plus ``total``, the full workspace workflow count. Page with ``offset`` when ``total`` exceeds ``limit``.
Get details for a saved workflow.
Create and save a new Workflow in the workspace. Do not invent the config. Start from a similar workflow (workflows_list, then workflows_get) and copy its shape; if one already fits, update it with workflows_update instead of creating a duplicate. Block types and their schemas are in the roboflow://workflows/blocks resources. Validate the config with workflow_specs_validate before saving. Validation and execution support OAuth and API-key connections with the required permissions. Once saved, execute the published workflow by URL slug with workflows_run. Saving does not test inference. Returns the created workflow including its document ID. Save this ID: it is required for workflows_update.
Update an existing saved Workflow's name and definition. Validate the config with workflow_specs_validate before updating. Validation and execution support OAuth and API-key connections with the required permissions. Block types and their schemas are in the roboflow://workflows/blocks resources. Use workflows_get to retrieve the current workflow first, then modify the config as needed.
Delete a saved Workflow, moving it to the workspace Trash. This is a soft delete: the workflow stays in the Trash for 30 days and can be restored with ``trash_restore_workflow`` using the workflow's document id from the delete response or ``trash_list``. After 30 days it is permanently removed.
List all available Workflow blocks with a short summary of each. Returns a list of blocks, each with manifest (schema key), type (the identifier used in specifications, e.g. 'roboflow_core/open_ai@v7'), name, block_type, and short_description. Use ``workflow_blocks_get_schema`` to get the full schema of a specific block.
Get the full schema of a specific Workflow block. Returns all properties, required fields, and descriptions for a block identified by its manifest key (as returned by ``workflow_blocks_list``) or by the ``type`` string used in Workflow specifications.
Validate a Workflow JSON definition without executing it. Check whether a workflow definition is syntactically and semantically correct before saving or running it. Example workflow definition — detects objects, enlarges bounding boxes, crops, runs a second detection filtering for dogs, and classifies the breed only when exactly one dog is found: .. code-block:: json { "version": "1.0", "inputs": [ {"type": "WorkflowImage", "name": "image"} ], "steps": [ { "type": "ObjectDetectionModel", "name": "first_detection", "image": "$inputs.image", "model_id": "yolov8n-640" }, { "type": "DetectionsTransformation", "name": "enlarging_boxes", "predictions": "$steps.first_detection.predictions", "operations": [ {"type": "DetectionsOffset", "offset_x": 50, "offset_y": 50} ] }, { "type": "Crop", "name": "first_crop", "image": "$inputs.image", "predictions": "$steps.enlarging_boxes.predictions" }, { "type": "ObjectDetectionModel", "name": "second_detection", "image": "$steps.first_crop.crops", "model_id": "yolov8n-640", "class_filter": ["dog"] }, { "type": "ContinueIf", "name": "continue_if", "condition_statement": { "type": "StatementGroup", "statements": [ { "type": "BinaryStatement", "left_operand": { "type": "DynamicOperand", "operand_name": "prediction", "operations": [{"type": "SequenceLength"}] }, "comparator": {"type": "(Number) =="}, "right_operand": { "type": "StaticOperand", "value": 1 } } ] }, "evaluation_parameters": { "prediction": "$steps.second_detection.predictions" }, "next_steps": ["$steps.classification"] }, { "type": "ClassificationModel", "name": "classification", "image": "$steps.first_crop.crops", "model_id": "dog-breed-xpaq6/1" } ], "outputs": [ { "type": "JsonField", "name": "dog_classification", "selector": "$steps.classification.predictions" } ] } Key patterns shown above: - ``$inputs.<name>`` references a workflow input. - ``$steps.<step_name>.<output>`` references another step's output. - ``ContinueIf`` enables conditional branching based on runtime values. - Steps can chain: detect → transform → crop → detect → classify. Returns validation status. A valid workflow returns ``{"status": "ok"}``. An invalid one returns error details.
Execute a saved Workflow on one or more images. Runs a previously created Workflow against the provided images on the Roboflow serverless infrastructure. This always hits the latest **published** version of the workflow, never an unpublished draft. Images are processed synchronously; calls with many images take proportionally longer. Workflow blocks may send data to external services or change existing records. Execution therefore requires the same care as those configured actions. Returns workflow outputs as defined by the workflow's output blocks.
Execute a Workflow from an inline JSON definition. Unlike ``workflows_run`` which runs a saved workflow by ID, this tool accepts a full workflow JSON spec and executes it directly. Useful for testing workflows before saving them, or for running a draft without publishing it. Validate the definition with ``workflow_specs_validate`` before running it; invalid specifications fail at execution time with less actionable serverless errors. IMPORTANT: Images must be public URLs or base64-encoded data. Local file paths do NOT work — the API runs remotely and cannot access your filesystem. Workflow blocks may send data to external services or change existing records. Execution therefore requires the same care as those configured actions. Returns workflow outputs as defined by the workflow's output blocks.
Describe the Workflow Evals API: operations, schemas, evaluators, and caller actions. Start here in an unfamiliar workspace. Returns ``workspace`` (the authenticated workspace URL slug, not the internal id), the public operation registry, each operation's required permission, the installed engine version, and which actions the current credential can perform. Never changes state.
List the evaluators available to Spec Checks in the installed engine. Returns ``{engineVersion, items}``; each item has ``type``, ``semanticType``, and its ``configSchema``. Use the ``type`` in a Spec Check.
Get one evaluator's description and configuration JSON Schema.
Get a JSON Schema for authoring Workflow Evals payloads. Read the ``spec`` schema before writing a Spec, ``eval-dataset`` before creating a Dataset, ``case`` before adding Cases, and ``binding-set`` before hand-writing bindings. The engine still performs semantic validation.
Get the machine-readable OpenAPI 3.1 contract for the Workflow Evals API. Large response. Prefer workflow_evals_capabilities and the per-tool descriptions; use this when you need exact request/response schemas.
Get the engine's agent manifest. Start here before designing or drafting an Eval. Returns ``{engineVersion, manifest}``: ``entrySkill`` plus IDs of skills, bundles, schemas, resources, tool contracts, and examples. To draft a Spec and its bindings yourself: 1. Read ``entrySkill`` (e.g. 'skill:workflow-evals') and the task skill (e.g. 'skill:create-eval') with workflow_evals_agent_resource_get. 2. Read the task bundle (e.g. 'bundle:create-eval') and fetch the schemas and examples listed in its ``assets`` with ``kind='asset'``. 3. Write the Spec from the user's intent, the Workflow's inputs/outputs (workflows_get), and the Dataset contract. Iterate with workflow_evals_specs_validate, then save with workflow_evals_specs_create. 4. Get bindings from workflow_evals_bindings_suggest (or write them), confirm with workflow_evals_bindings_validate, and review both with the user. If ``engineVersion`` changes between calls, reload the manifest.
List engine-owned agent skills or bundles. Returns ``{engineVersion, items}``.
Get one engine-owned agent resource. ``skill`` returns Markdown ``content``; ``bundle`` returns the parsed ``bundle`` whose ``assets`` IDs can be fetched with ``kind='asset'`` (schemas, resources, tool contracts, examples). Unknown IDs or IDs from another category return 404.
Poll a Workflow Evals deletion operation. Returns a sanitized receipt ``{operationId, kind, state, resource}``, readable even after the deleted resource is gone.
List Evals in the workspace, newest first. Returns ``{items, nextCursor?}``. Items include setup ``state`` (``draft``/``ready``), ``runCount``, and ``lastRunAt``.
Create an Eval. Every field is optional; an empty call creates a draft. The Eval becomes ``ready`` once it has an engine-valid Spec and a compatible Eval Dataset. If it has an authoring Workflow Subject, its ``subject_bindings`` must also map every outcome check output. Missing output mappings keep it ``draft`` with ``missing_bindings`` diagnostics; use workflow_evals_bindings_suggest and workflow_evals_bindings_validate to prepare the mappings. Returns the Eval detail including its ``revision`` (needed for workflow_evals_update).
Get one Eval by ID or by its readable URL (exactly one). Returns setup ``state`` and diagnostics (including ``missing_bindings`` for unmapped authoring Workflow check outputs), current Spec/Dataset projections, ``subjects``, ``subjectBindings``, ``serverConfiguration``, recent Runs, and the ``revision`` used for updates.
Update an Eval under optimistic concurrency. Omitted fields are preserved; ``clear_fields`` sets fields to null. The response re-derives ``draft``/``ready``. An authoring Workflow with unmapped outcome check outputs stays ``draft`` with ``missing_bindings`` diagnostics; supply its output mappings in ``subject_bindings``. Existing Runs never change.
Delete an Eval with all its Runs, Executions, results, and owned artifacts. Two steps. First call without ``deletion_key``: nothing is deleted; returns ``{confirmationRequired: true, deletionKey, impact}``. Show the impact to the user and get explicit confirmation, then call again with ``deletion_key``. That admits deletion and returns ``{asyncTaskId, statusUrl}``; poll with workflow_evals_operation_get. Shared Specs and Datasets are kept.
List live Specs in the workspace. Returns ``{items, nextCursor?}``.
Validate, compile, and save a Spec. Invalid Specs return 422 with engine diagnostics. Draft the Spec yourself following the engine skills (start at roboflow://workflow-evals/manifest) and iterate with workflow_evals_specs_validate before saving. Confirm the Spec with the user first.
Get the current live Spec and its ``revision``.
Replace a live Spec's policy and/or metadata. The full result is recompiled. Existing Runs keep the Spec they froze.
Validate an unsaved Spec: compile diagnostics plus derived ground-truth requirements. Saves nothing.
List Eval Datasets whose inputs and ground truth satisfy a Spec.
List Eval Datasets with declared contracts, Case counts, slices, and completeness.
Create an empty Eval Dataset with declared input and ground-truth contracts. Add Cases with workflow_evals_cases_create or workflow_evals_cases_import. Adding Cases never changes the contracts; use workflow_evals_datasets_update_contract.
Get an Eval Dataset and its derived summary (no Cases inline) plus ``revision``.
Update Eval Dataset metadata (name/description).
Replace a Dataset's declared input and/or ground-truth contract. A schema-only change returns the updated Dataset. A change that rewrites Cases returns 202 with an AsyncTask (poll with async_tasks_get); Case writes are rejected until it completes.
List Specs whose input and ground-truth requirements this Dataset satisfies.
List Cases in an Eval Dataset (summaries, no media bytes).
Add one Case to an Eval Dataset, validated against the Dataset's contracts. A Run that selects an incomplete Case is rejected with ``EVAL_NOT_READY`` and the ``incompleteCaseIds``.
Get one complete Case with short-lived read URLs for its assets and its ``revision``.
Replace a Case atomically (full replacement, not a field patch). Read workflow_evals_cases_get first and preserve its name, groundTruthState, slices, and evidenceRefs unless deliberately changing them. Set ground_truth_state to complete only when approving the ground truth. Runs that froze the Case keep their copy.
Remove a Case from the live Dataset. Runs that already froze it stay readable.
Bulk-import images from Roboflow sources, project datasets, or uploaded artifacts. Returns 202 ``{intakeId, asyncTaskId, status, pollUrl}``; poll with workflow_evals_case_imports_get. Imported Cases start with incomplete ground truth and cannot be run until it is filled in (workflow_evals_cases_replace). At most 10,000 Cases per intake. Source imports need image:read; dataset imports need project:read and image:read.
Poll a Case import. ``status`` is queued, running, completed, partially_completed, failed, or cancelled; ``progress`` has discovered, processed, adopted, failed, total. List Cases with workflow_evals_cases_list while it runs.
Start uploading a local image as Case input. The MCP server never receives bytes. Returns ``{uploadId, artifactId, uploadUrl, requiredHeaders, expiresInSeconds}`` and ``instructions``. Then: 1. HTTP PUT the file bytes to ``uploadUrl`` with exactly ``requiredHeaders``. 2. Call workflow_evals_case_assets_upload_complete(eval_dataset_id, upload_id). 3. Use ``{'artifactId': ...}`` as the image input in workflow_evals_cases_create.
Verify and publish an uploaded Case image. Returns the stable ``artifactId``. Checks size, type, and that the bytes decode as an image. Call only after the PUT to the signed URL succeeded.
Propose a BindingSet mapping a Spec's inputs/outputs onto a Workflow Subject. Returns the proposal and the normalized ``workflowSubject``. Nothing is saved; show the proposal to the user and confirm it with workflow_evals_bindings_validate. Saved Workflow Subjects also need workflow:read.
Validate a BindingSet against a Spec, Dataset, and Subject. Returns ``{valid, diagnostics, ...}`` with the planned capture contract. A valid BindingSet is what an Eval Run executes against. Saved Workflow Subjects also need workflow:read.
Run the Eval's Workflow over Dataset Cases to produce candidate outputs. Costs inference. Helps label ground truth and gives AI drafting real output shapes. Returns 202 with the preparation (``id``, ``state``, progress counters). Poll with workflow_evals_case_preparations_get and read outputs with workflow_evals_case_preparations_cases.
Get a Case preparation's state and progress (current one when no ID is given). Returns ``{}`` when the Eval has no current preparation.
Resume a preparation, keeping successful Cases and requeueing only failed ones.
List candidate outputs per Case. Each success has a short-lived ``candidateOutput.readUrl``. Fetching ``readUrl`` returns the raw Workflow output keyed by output name.
List an Eval's Runs, newest first. ``limit=1`` gives the latest Run.
Start one grouped Run that evaluates every Subject on the Eval's Spec and Dataset. Each execution needs its own valid Subject and BindingSet, even when the Eval's authoring Workflow is ``draft`` due to ``missing_bindings``. Costs inference for server runtimes. Returns 202 with ``run``, ``executions``, and ``asyncTaskId`` (null for local runtimes, which use workflow_evals_executions_input_cases / submit_capture). Poll workflow_evals_runs_get until the state is terminal. A one-Case selection is a cheap dry run. Server runtimes also need model:infer; saved Workflow Subjects also need workflow:read.
Get a Run's lifecycle state, child Execution counts, and ``retry`` eligibility. Poll this while the Run is active; refresh results once it is terminal. With ``wait_seconds`` the tool polls for you and returns early when the state is one of ``completed``, ``partially_completed``, ``failed``, or ``cancelled``.
Get a Run's frozen shared configuration: Spec, Dataset snapshot, and Case selection.
Request cancellation of a queued or running Run. Idempotent.
Retry only missing or operationally failed Cases in the same Run. Check ``retry.allowed`` from workflow_evals_runs_get first. Keeps the frozen setup; to change the Workflow, use workflow_evals_runs_replay. Server-runtime retries also need workflow:read and model:infer.
Create a new derived Run from a source Run, optionally with new Subjects. Returns 409 if the saved Spec or Dataset changed since the source Run. Server runtimes also need model:infer; saved Workflow Subjects also need workflow:read.
Score retained Workflow outputs against a revised Spec without re-running Workflows. Creates a new derived Run. Incompatible Executions return rerun-required diagnostics.
Delete a Run with its Executions and results. Two steps. Without ``deletion_key`` nothing is deleted; returns ``{confirmationRequired: true, deletionKey, impact}``. After the user confirms, call again with the key; returns ``{asyncTaskId, statusUrl}``. Poll with workflow_evals_operation_get.
List a Run's Executions (one per evaluated Workflow Subject).
Get one Execution's lifecycle, frozen Subject identity, and result availability.
Get an Execution's frozen Subject manifest, BindingSet, and linked plan.
Page through an Execution's input Cases for a client-owned (local) runner. Only needed when the Run uses a local runtime. Each item has the ``case``, ``shardIndex``, and ``checkpoint`` (absent means not yet submitted); ``artifactReadUrls`` holds short-lived input image URLs. Run inference yourself, then submit each output with workflow_evals_executions_submit_capture.
Submit one Case's Workflow output from a local runner. The platform scores it. Identical repeats are idempotent; different bytes for the same attempt return 409; a stale attempt returns 412.
Get an Execution's aggregate per-Check performance and runtime summary.
List per-Case results for an Execution with compact ``checkResults`` by Check ID. Use ``failed_check=True`` to find failures, then workflow_evals_results_case_get for details.
Get one Case's result: inputs, frozen ground truth, bound actual values, and Check results. The raw Workflow output is omitted by default (``rawOutputOmitted: true``); the values the Checks scored are in ``actualValues`` and ``caseResult.boundOutputs``.
Compare completed Executions: per-Check deltas and a page of Case-level deltas. Pure read; sibling Executions from one Run are always comparable.
Start a server-side export of a Run's results. Returns 202 with ``asyncTaskId``; poll workflow_evals_exports_get_job until it completes, then use its download URL (renew with workflow_evals_exports_download_url). A Run with retryable failed Cases is refused with 409 ``retryFirst`` unless ``allow_pending_retries`` is true.
Poll an export. ``{asyncTaskId, state, progress, result?}``; ``result`` has the artifact and download URL.
Get a fresh short-lived download URL for a completed export.
Generate (or reuse) a 2D embedding projection of an Execution's input images. New Runs schedule this automatically; use it for older Runs or explicit retries. Returns the job; poll with workflow_evals_embeddings_get.
Get embedding analysis jobs. Never launches analysis. With ``provider`` or ``async_task_id``, returns ``{job}`` (``job`` is null when none exists). With neither, returns ``{jobs: {<provider>: job | null}}`` for every provider, plus ``errors: {<provider>: message}`` for providers that could not be read. Completed jobs have ``result.url``: a file with 2D ``points`` per Case (coordinates 8..92) plus ``skipped`` Cases. New Runs start these jobs on their own.
Request cooperative cancellation of an embedding job.
Queue a durable Workflow run over an Asset Library selection. The platform owns selection authorization, entitlement and billing, workflow compatibility, staging, and job registration: it stages your selection into a Data Staging batch for you (for files you stage yourself, use ``batch_processing_run`` or ``batch_processing_staged_job_start``). The response is a 202 receipt: poll ``batch_processing_asset_library_task_get`` with its taskId until terminal, then use ``batch_processing_job_get`` with jobId.
Poll the launch receipt until its durable job is registered.
Route a bulk image/video processing request onto batch processing: pick the staging mode, settle the batch id, and return the exact inference-cli commands for the whole run. Every batch processing job runs a Workflow over a Data Staging batch; the input paths differ only in who fills it. Files already in Roboflow (Asset Library): batch_processing_asset_library_job_create, and the platform selects and stages them for you. External files (local disk, cloud bucket, references file) when you only want the outputs: stage them with the inference-cli and drive the run with batch_processing_run (nothing is imported; the classic ETL shape). External files you want INSIDE Roboflow for labeling/training/curation: that is an import, not a job; mirror them with a datasource (bucket mirror, connect_cloud_storage), then run an Asset Library job over the imported images if you also want bulk predictions (the classic ELT shape). Staging uploads are client-side: this MCP server cannot read the user's filesystem or cloud credentials, so files are staged with the inference-cli on the user's machine (pip install inference-cli). Call this with whatever you already know (local dir, bucket path, workflow, images vs videos); it returns the install line and the ordered stage/inspect/process/monitor/export commands. Read the skill://roboflow/roboflow-batch-processing/SKILL.md resource for the full recipe, and prefer batch_processing_run to drive the run server-side once files are staged. Requires the batch-processing feature on the workspace.
List the workspace's data-staging batches (inputs and job results). Returns ``{batches, nextPageToken?}``. Batches expire about 7 days after creation. Job results appear as platform-generated batches named ``<job-id>-processing`` and ``<job-id>-export``.
Get a staged batch's metadata, file count, and ingest progress. Sharded, cloud-storage, and references ingests register files asynchronously: the count stays low until ingest workers finish. Poll this until ``ingest.pending`` is false and ``ingest.failed`` is false before starting a job. For multipart batches (e.g. job results) the response includes ``parts``.
List a staged batch's files with time-limited signed download URLs. Use this to download the results of a finished job (the ``<job-id>-export`` batch). Job-result batches are multipart: when the batch has exactly one part it is selected automatically (and echoed as ``partName``); with several parts, pass ``part_name`` (see ``batch_processing_staging_batch_get`` parts). Download URLs expire after ~24h; archives (.tar/.tar.gz) must be unpacked after download. Returns ``{files, returned, nextPageToken?, truncated, partName?}``. Results are returned in whole upstream pages so ``nextPageToken`` always continues exactly where ``files`` ended. Listings are capped at 10,000 entries per call; past that, pull results with the inference-cli's ``export-batch`` (resumable) instead.
List the workspace's batch processing jobs. Returns ``{jobs, nextPageToken?}`` with each job's full definition omitted (use ``batch_processing_job_get`` for one job's detail). Each entry carries ``inputSource``: 'asset-library' (platform-staged selection) or 'staged-batch' (a batch the caller staged).
Get a job's status and per-stage progress. Poll this to track a running job: ``job.isTerminal`` says whether it finished and ``job.error`` whether it failed; ``stages`` carries per-stage progress and ``outputBatches``. When the export stage completes, download results from the ``<job-id>-export`` staging batch via ``batch_processing_staging_batch_files_list``.
Start a batch processing job: run a Workflow over a staged batch. This launches asynchronous compute and consumes credits. The batch must be staged first (see ``batch_processing_guide``) and fully ingested (``batch_processing_staging_batch_get``). Returns ``{jobId, ...}``; poll ``batch_processing_job_get`` and fetch results from the ``<job-id>-export`` staging batch when it finishes. Re-running with the same job_id and identical settings is idempotent; a divergent definition is rejected (409).
Abort a running batch processing job. Already-produced partial results stay available in the job's staging batches.
Restart a failed or aborted job, optionally overriding compute parameters. Consumes credits like a fresh run.
Fetch a job's processing logs (paginated). Use this to diagnose failed or slow jobs; pair with batch_processing_job_get for stage status.
Master tool: drive a batch processing run over a staging batch you name (stage -> ingest -> job -> results) through repeated resumable calls. For Asset Library selections, use batch_processing_asset_library_job_create instead. Every batch processing job runs a Workflow over a Data Staging batch; the input paths differ only in who fills it. Files already in Roboflow (Asset Library): batch_processing_asset_library_job_create, and the platform selects and stages them for you. External files (local disk, cloud bucket, references file) when you only want the outputs: stage them with the inference-cli and drive the run with batch_processing_run (nothing is imported; the classic ETL shape). External files you want INSIDE Roboflow for labeling/training/curation: that is an import, not a job; mirror them with a datasource (bucket mirror, connect_cloud_storage), then run an Asset Library job over the imported images if you also want bulk predictions (the classic ELT shape). Each call reads current state, advances what it can, and returns immediately: 'staging_required' (batch missing; response contains the inference-cli commands to run), 'ingest_in_progress', 'ingest_failed', 'running' (job started or working; includes stage progress), 'completed' (includes result files with download URLs), or 'failed' (includes logs). This server never sleeps on your behalf; non-terminal responses carry retryAfterSeconds, so wait that long and call again with the returned job_id to resume; omit optional creation settings and the stored paid-job definition remains authoritative. The job is started under an id derived from (workspace, batch, workflow), so retrying after a lost response re-registers the same job rather than starting a second one. Starting the job consumes credits. For the advanced knobs (max_runtime_seconds, max_parallel_tasks, max_image_failure_rate, image_outputs_to_save) use batch_processing_staged_job_start instead.
List devices registered in the workspace. Returns a list of Device objects with id, name, status, last_heartbeat, platform/hardware info, tags, and created_at. ``status`` is ``online`` if a heartbeat was received within the last 5 minutes, otherwise ``offline`` (or ``unknown`` for devices that have never reported). Requires the ``device:read`` scope. Device-scoped api_keys cannot call this endpoint and will receive 403.
Provision a new v2 device. Requires the ``device:update`` scope. Returns ``{deviceId, installId, offlineProvisioningQrPayload?}``: ``installId`` is the short-lived token used by the device installer (``GET /devices/v2/:installId/install.sh``). ``offlineProvisioningQrPayload`` is only present for AI1 devices provisioned with ``offline_mode=true``.
Get a single device by id. Returns the Device object. 404 if the device does not exist or belongs to a different workspace. When inspecting a device, also call ``devices_get_config`` for its running services and ``devices_get_default_config`` for the workspace's recommended versions. Comparing the two ``services`` maps reveals whether the device is up to date or pinned to an older build of any service.
Get the device's current runtime configuration. Returns the full RFDM config JSON: ``device_id``, ``device_name``, ``workspace_id``, ``version``, ``last_updated``, ``config``, ``services``, and any ``pendingUpdates`` (queued changes with ``applyUpdatesAt`` and ``updateFields``). The returned config is active state; queued changes have not reached the device yet. Workspace and OAuth callers receive redacted stream credentials. Service environment variables can still contain integration credentials, so treat the payload as sensitive. Tip: pair this with ``devices_get_default_config`` and diff the ``services`` map. The default config carries the workspace's recommended version for each service, so comparing the two tells you whether the device is up to date or pinned to an older build.
Get the workspace's default device configuration. Returns ``{config, patch}``: ``config`` is the base default config with the workspace's ``config_patch`` applied (the template used when provisioning new devices, including default service versions), and ``patch`` is the raw workspace-level patch object. Useful for inspecting which service versions a fresh device would be created with, or for seeding a payload to ``devices_update_config``. Requires the ``device:read`` scope. Device-scoped api_keys are rejected with 403 — this endpoint is workspace-wide.
Update the device's runtime configuration. Requires ``device:update``. Uses JSON Merge Patch, so a small nested change preserves sibling settings; null explicitly deletes a key. Deployment-affecting changes wait for the next maintenance window when one is configured and not currently active. Schedule, timezone, and device name/type changes apply immediately. Returns ``{success, config, deferred}``. Check ``deferred`` and ``config.pendingUpdates`` before claiming the change is live. ``force_apply`` and ``immediate_delta`` are query-only controls, not fields in the config payload. Enabling Vision Events backup additionally requires the platform's ``vision-events:write`` scope.
Pin one service's version without replacing the rest of the config. Requires the ``device:update`` scope. Respects the maintenance window and queued changes. Returns ``{success, deferred}``; success means the config was saved, not that the device installed the version.
List prior configuration revisions, newest first. Returns ``{data: ConfigRevision[], pagination: {next_cursor, has_more, limit}}``. Each ConfigRevision carries ``revision_id``, ``created_at``, and ``created_by``.
Request a restart of the device's inference runtime. Interrupts running pipelines. This restarts inference, not the host operating system. Returns ``{id}`` for the queued command, not proof that the restart completed. Follow up with ``devices_get_snapshot`` or ``devices_get_events`` to verify recovery. Offline devices cannot execute commands; undelivered commands expire after 5 minutes. Do not retry automatically, because each call queues another restart.
Request camera discovery on a device through its command channel. Returns ``{id}`` for the queued command. Discovery runs asynchronously; read ``devices_get`` or ``devices_get_snapshot`` afterward for ``discovered_cameras`` and ``devices_get_events`` for discovery/connection events. A successful enqueue does not mean discovery finished. Undelivered commands expire after 5 minutes, and discovery support depends on the device runtime.
Request a pause of a running device stream without removing its config. ``pipeline_id`` targets the edge pipeline. Pass ``stream_id`` from the same Stream object when it is a platform record; omit it for a ``provisioning`` entry, whose id is only the stream name. Returns ``{id}`` for the queued command, not completed execution. Read ``devices_streams_get`` afterward to confirm the status. Undelivered commands expire after 5 minutes.
Request that a paused device stream resume processing. ``pipeline_id`` targets the edge pipeline. Pass ``stream_id`` from the same Stream object when it is a platform record; omit it for a ``provisioning`` entry, whose id is only the stream name. Returns ``{id}`` for the queued command, not completed execution. Read ``devices_streams_get`` afterward to confirm the status. Resuming a configured Workflow can execute external actions. Undelivered commands expire after 5 minutes.
Request one Workflow execution on a trigger-driven device stream. The platform resolves the Workflow and workspace from the stream or device config. Camera capture must be enabled for the workspace. The Workflow may write to external integrations, so do not retry automatically. Returns ``{id}`` for the queued command, not inference output or proof of completion. Follow up with ``devices_get_events`` and ``devices_streams_get`` for status. Undelivered commands expire after 5 minutes.
Request a power cycle of one camera's PoE port on supported edge hardware. Interrupts the camera and its stream while power is cycled. Choose the interface associated with the affected camera, not an arbitrary network interface. Returns ``{id}`` for the queued command, not a completed reset. Follow up with ``devices_get_events`` and ``devices_streams_get`` to verify recovery. Each call requests a new power cycle; undelivered commands expire after 5 minutes.
Create a stream on a device through the ``add_stream`` command. Requires the ``device:update`` scope. On V2 devices the platform applies this as an immediate config update (``status: "applied"``, no command id), and the stream shows in ``devices_streams_list`` as ``provisioning`` until the device reports it running. The Workflow may write to external integrations once the stream runs.
Remove a stream from a device permanently. Requires the ``device:update`` scope. On V2 devices the stream is removed from the device config at once (``status: "applied"``). Otherwise a ``terminate_stream`` command is queued, and the device targets the pipeline by ``pipeline_id``. To stop processing temporarily use ``devices_streams_pause``. ``devices_streams_delete`` removes only monitoring state, so a configured stream comes back after it.
Read the secure gateway's recorded bootstrap and cache state. Returns the platform's gateway state, including ``status`` (``initialising``, ``ready``, or ``error``), gateway/SeaweedFS versions, timestamps, cache stats, and any last setup error. A 404 means no state has been recorded for this device. This does not initialise a gateway or verify current connectivity.
List streams configured on the device. Returns a list of Stream objects, including streams that exist only in the device config and have not been reported by the device yet (``status: "provisioning"``, ``provisioning: true``). ``mode`` is ``"triggered"`` for trigger-driven streams, ``"continuous"`` otherwise. Credential-bearing fields (URL userinfo, ``password``, ``credential``, etc.) are redacted from the ``source`` and ``configured_source`` fields. ``id`` is the platform stream record, while ``pipeline_id`` is the runtime pipeline identifier. Use both values from the same object when pausing or resuming. Structured ``error_code``, ``error_message``, and ``error_retryable`` describe the latest status-event failure; null means the field was not reported.
Get a single stream by id. Returns the Stream object. Streams that exist only in the device config are returned as synthesized ``provisioning`` entries rather than 404; 404 only if the stream exists neither live nor in config. Includes structured ``error_code``, ``error_message``, and ``error_retryable`` alongside the legacy ``error`` text.
Fetch device logs from Elasticsearch. Rate-limited at 120 requests / minute per workspace, in a separate bucket from device log ingestion. Returns ``{data: LogEntry[], pagination: {next_cursor, has_more, limit}}``.
Get aggregated hardware metrics and device health sections. Rate-limited per-device: 60 requests / minute steady, plus a burst limit of 10 requests / 10 seconds. By default returns ``{time_period, bucket_interval, fill_interval_seconds, buckets, stream_fps, system_status, services, hardware, network_interfaces, metadata}``: - ``buckets`` — cpu/memory/disk/gpu plus ``network_upload_bytes_per_sec`` / ``network_download_bytes_per_sec`` - ``stream_fps`` — one series per running pipeline (``pipeline_id``, ``stream_name``, ``stream_id``) with a ``buckets`` array in ascending time order, each entry ``{bucket_start, camera_fps, inference_fps}`` - ``system_status`` — per-bucket docker daemon and NTP health (``up`` / ``partial`` / ``missing``; ``missing`` = no telemetry samples in that bucket) - ``services`` — per-service container status with the latest container sample (image, cpu, memory); add ``service_history`` to ``include`` for per-bucket history - ``hardware`` — most recent startup hardware report (OS, CPU, Jetson/JetPack, GPU driver, uptime, NTP) - ``network_interfaces`` — most recent interface snapshot Pass ``include=metrics`` for the compact time-series-only response, or ``include=stream_fps`` when you only need camera vs. inference frame rates.
Get the device's deployment history with per-deployment activity. This is the device Activity tab as structured JSON: each config revision becomes a half-open deployment window (newest window open-ended), annotated with what happened while it was live: - ``exception_issues`` — exceptions grouped by fingerprint with occurrence counts, last_seen, and the latest description; drill into one with ``devices_get_exception_occurrences`` - ``error_event_issues`` — error events grouped by entity/event/error_code - ``execution_environment`` — the inference runtime reported during the window (versions, GPU, loaded models) - ``workflow_edits`` — workflow publishes that landed mid-deployment - ``container_pulls`` — image pulls (and failures) during the window - ``stats`` — unique/unhandled exception counts and error event count - ``config_changed_paths`` (opt-in) — dotted config paths changed vs the prior revision, values omitted - ``trends`` (opt-in) — bucketed occurrence time series per issue Returns ``{device_id, deployments: Deployment[], pagination: {next_cursor, has_more, limit}}``. Prefer this over raw ``devices_get_events`` when diagnosing what a deployment broke. Rate-limited per-device: 30 requests / minute.
List raw occurrences of one exception fingerprint, newest first. Use after ``devices_get_deployments`` to see exactly when a grouped exception fired — each row is ``{id, timestamp, error_code}``. Pair the timestamps with ``devices_get_logs`` (``start_time`` / ``end_time`` around an occurrence) to read the surrounding log context. Returns ``{data: [...], pagination: {next_cursor, has_more, limit}}``.
Get the full current state of a device in one call. Prefer this as the FIRST call when diagnosing a device — it aggregates what would otherwise take six requests: - ``device`` — identity, online/offline status, hardware summary, network interfaces, discovered cameras - ``streams`` — ``{total, running, data}`` including config-only (provisioning) streams - ``services`` / ``services_summary`` — per-service container status and healthy/total counts - ``telemetry`` — the latest non-empty 1h telemetry bucket (cpu, memory, disk, gpu, network throughput) - ``system_status`` — current docker daemon and NTP health - ``hardware`` — most recent startup hardware report - ``current_deployment`` — the live config revision with its exception/error issues and execution environment - ``recent_events`` — the 20 most recent lifecycle events Sections are best-effort: a failed section is ``null`` and named in the top-level ``errors`` array. Follow up with the focused tools (``devices_get_deployments``, ``devices_get_logs``, ``devices_get_telemetry``) for history and detail. The ``services`` section here is container status only. For typed sidecar state (is the PLC connected, is the event store full) call ``devices_get_services`` or the per-sidecar tools. Rate-limited per-device: 30 requests / minute.
List device and stream lifecycle events. Returns ``{data: Event[], pagination: {next_cursor, prev_cursor, has_more, limit}}``. By default the feed models **state transitions**: consecutive rows carrying the same event name for the same entity collapse into one row unless the previous row's TTL has elapsed. That is right for lifecycle events and wrong for periodic telemetry, which reuses a single event name for every sample: ``plc_snapshot`` ticks every 60s with ``ttl_s: 300``, so a deduped read returns roughly one row where the raw read returns them all. Pass ``dedupe=False`` to read raw rows. It requires **both** ``entity_type`` and ``entity_id`` (an entity id is only unique within its type), reports ``event_end_timestamp`` as ``null`` (an "end" is derived from the dedup window and means nothing for a sampled reading), and is rate-limited at 30 requests / minute per device, in the same bucket as ``devices_get_services`` and ``devices_get_service_series``. The deduped default is not rate-limited. For charting a named sidecar metric, prefer ``devices_get_service_series``, which resolves the entity id and the dedup behavior for you.
List the sidecar containers a device runs and what each is doing. Joins the device's declared ``services`` config with the same latest-value status cache the Device Manager UI subscribes to. Returns ``{device_id, services: Service[], unassociated_signals}``. Each Service carries ``name``, ``kind`` (resolved from the image; an unrecognized container is ``custom``), ``image``/``tag``, ``tag_is_canonical``, ``automatic_updates``, ``has_pending_changes``, ``state`` plus ``state_reported_at`` / ``state_received_at``, ``image_state``, ``signal_conflicts``, and the typed ``status`` for its kind. Reading the nulls correctly: - ``state`` and ``image_state`` are ``null`` once the last report has aged past its TTL; the matching ``*_received_at`` still carries a timestamp, so "stale reading" stays distinguishable from "never reported". - ``status`` is ``null`` until the service has reported, for kinds that emit no telemetry (``rtsp_simulator``, ``device_hmi``, ``custom``), and whenever ``signal_conflicts`` is non-empty. - ``signal_conflicts`` lists entity ids more than one declared service claims. Ids derive from the **kind**, so two services of the same kind collide unless each sets a distinct ``DEVICE_EVENT_ENTITY_ID``. The reading cannot be attributed, so it is withheld rather than guessed. - ``unassociated_signals`` holds telemetry that matched no declared service (a custom container, or an entity-id override we could not resolve). It needs ``include=['signals']`` and is omitted when a ``kind`` filter is applied. Two clocks, everywhere in this response: ``*_reported_at`` is the device's own claim and is ``null`` when the device sent none (it is never backfilled), while ``*_received_at`` is when the platform recorded it. Freshness reads ``received_at``; ordering two signals from one device reads ``reported_at``. Never compare one against the other. ``metrics_truncated: true`` means the metrics aggregation hit its row cap and some services report ``metrics: null`` for that reason rather than never having reported. Narrow ``time_period``. Rate-limited per-device: 30 requests / minute, in one bucket shared with ``devices_get_service_series``, the per-sidecar tools, and ``devices_get_events(dedupe=False)``.
Answer "is this PLC connected?" for a device's PLC relay sidecars. Thin view over ``devices_get_services(kind='plc_relay')``. Returns ``{device_id, services: Service[]}``; each ``status`` carries: - ``connected``: reconciled across the every-60s snapshot and the transition-only connectivity events by recency, connectivity winning ties, so an older optimistic snapshot can never mask a newer disconnect. ``null`` means unknown, not disconnected: the two slots could not be ordered on one clock. - ``driver``, ``plc_ip`` - ``tags`` / ``tag_count``: the tag map and its size, **withheld (``null``) whenever ``connected`` is not true**. Those readings predate the drop, and a frozen part count shown as current is how an operator ends up trusting a dead line. - ``reported_at``: device clock, from the snapshot; ``connection_changed_at``: device clock, from the last connectivity transition. Both ``null`` when that slot never reported. - ``stale: true``: the reading that decided ``connected`` is old (over 30 minutes), which is different from absent. For connectivity history, use ``devices_get_service_series`` with ``metric='connected'`` (charts as 1/0).
Report a device's local event store against its capacity limits. Thin view over ``devices_get_services(kind='event_store')``. Returns ``{device_id, services: Service[]}``; each ``status`` carries ``records`` / ``records_limit`` / ``records_percent``, ``images``, ``bytes_used`` / ``bytes_limit`` / ``bytes_percent``, a ``backup`` block (Vision Events upload progress: ``enabled``, ``backed_up_*``, ``pending_*``), a ``drafts`` block, ``disk``, ``capacity_blocked``, ``unuploaded_records``, and ``last_cleanup``. Reading it correctly: - ``capacity_blocked`` is ``null`` until the device reports a transition. The service emits only ``capacity_blocked`` / ``capacity_cleared``, so silence is genuinely unknown and ``false`` would assert healthy. It also reads ``true`` only while a fresh stats sample has not contradicted it. - ``drafts`` is ``null`` on firmware predating the draft lifecycle, which is not the same as a device reporting zero drafts. - ``stale: true`` with all counters ``null`` means no recent stats sample: a device that only ever reported a cleanup is not a healthy, current event store. - ``reported_at`` is the device's clock and may be ``null``; the ``received_at`` fields are the platform's. For a trend (fill rate, backup backlog), use ``devices_get_service_series`` with metrics such as ``records_percent``, ``bytes_percent``, ``pending_records``, or ``disk_percent_used``.
Chart one named sidecar metric over time. The metric name resolves to the right entity id, event names, and metadata key for that service's kind, and the read skips the dedup window that would otherwise collapse periodic telemetry. Use this for trend questions instead of raw ``devices_get_events``. Returns ``{device_id, service, kind, metric, metric_type, time_period, available_metrics, truncated, covered_from, covered_to, points: [{timestamp, value}]}``. - ``metric_type`` is ``number`` or ``boolean``. A boolean charts as 1/0, so the type is what tells a ``1`` meaning "true" from a ``1`` meaning "one". - An unknown ``metric`` returns 400 listing the valid names for that kind in ``valid_values``; ``available_metrics`` on a successful response says the same thing. - ``truncated: true`` means the window held more than the 5,000 sample cap. The newest samples are kept, so ``covered_from`` / ``covered_to`` report the interval actually returned, which can be shorter than the requested window. ``plc_snapshot`` ticks every 60s (10,080 samples over ``7d``), so narrow the window for full coverage. - Two clocks: ``time_period`` selects by when the platform *received* a sample, while each point's ``timestamp`` (and therefore ``covered_from`` / ``covered_to``) is what the device reported. On a badly-skewed device those can fall outside the requested window; that is the device's own account, not a filtering error. - 409 means two services of this kind claim the same entity id, so the samples cannot be attributed to one of them; the response names the claimants. Rate-limited per-device: 30 requests / minute, in one bucket shared with ``devices_get_services``, the per-sidecar tools, and ``devices_get_events(dedupe=False)``.
Rename a device, edit its environment variables, or set its workflow, live sampling or production mode. Requires the ``device:update`` scope. For runtime configuration (streams, services, versions) use ``devices_update_config``.
Delete a device and revoke its api_keys. Cannot be undone. Requires the ``device:update`` scope on a workspace credential; a device's own api_key cannot delete it (403).
Queue a command on the device's command channel. Requires the ``device:update`` scope. Returns ``{id}``; the device picks the command up on its next poll. Camera-capture commands (``livesample``, ``trigger_stream``) 403 when the workspace has the camera stream disabled.
Mint a fresh install id to reinstall an existing device. Requires the ``device:update`` scope on a workspace credential. Returns ``{deviceId, installId, offlineProvisioningQrPayload?}``; the device runs ``GET /devices/v2/:installId/install.sh``.
Mint the offline (Lite) provisioning QR payload for a device. Requires the ``device:update`` scope on a workspace credential and the workspace's roboflowLiteMode feature. Returns ``{installId, offlineProvisioningQrPayload}``.
Start building a ready-to-flash OS Lite image for a device. Requires the ``device:update`` scope on a workspace credential and the OS Lite image builder feature. Returns ``{jobId, reused, warnings}``; poll ``devices_os_image_get`` for status and the download link.
Get the device's in-flight or last finished OS Lite image job. Requires the ``device:update`` scope: the finished image embeds the device's credentials. Returns ``{job, nanoWifiAvailable, osImage}``.
Apply config updates staged for the device's next maintenance window now. Requires the ``device:update`` scope. A no-op when nothing is staged.
Replace the workspace default device config patch. Requires the ``device:update`` scope. The merged result is validated against the RFDM config schema (400 with ``details`` on failure). New devices start from this config.
Merge fields into a stream's ``data`` map. Requires the ``device:update`` scope. To change what the stream runs, edit ``stream`` in the device config with ``devices_update_config``.
Remove a stream's state document. Requires the ``device:update`` scope. Remove the stream from the device config too (``devices_update_config``), or the device recreates it.
Add the stream's latest frame to a project. Requires ``device:read`` plus ``image:create`` on a credential not limited to project groups. 403 when the workspace has the camera stream disabled.
Look at what a device camera sees right now. Returns the frame as an image plus ``image_url``: a signed URL, valid for an hour, that Workflow and model tools accept as an image input. Use it to design a Workflow against the real scene, then run the Workflow on ``image_url`` to check it before deploying to the device. Requires the ``device:update`` scope: when no frame is under 10s old the platform asks the device to start sending preview frames and waits. 504 means the device sent none in time (offline or stalled stream); 403 means the workspace disables camera viewing.
Snooze the device's health alerts for one day. Requires the ``device:update`` scope. Returns ``{deviceId, alerts_snoozed_until}``.
List lifecycle events across every device in the workspace. Requires the ``device:read`` scope. For one device's events with dedupe control use ``devices_get_events``.
Get the inference server version each listed device runs. Requires the ``device:read`` scope. Use it to check whether a workflow's blocks are supported before deploying it to a device.
List every device's stream ids and inferred camera family. Requires the ``device:read`` scope. Stream URLs are never returned.
List the workspace's fleet device groups. Requires ``device:read``.
Get one fleet device group. Requires ``device:read``.
Create a fleet device group with at least one member. Requires ``device:update``.
Update a fleet device group. Requires ``device:update``. ``device_ids`` replaces the whole membership. To add or remove single devices use ``device_groups_add_devices`` or ``device_groups_remove_devices``.
Add devices to a fleet device group; other members are kept. Requires ``device:update``.
Remove devices from a fleet device group; the devices are kept. Requires ``device:update``.
Delete a fleet device group; its devices are kept. Requires ``device:update``.
Get a fleet device group's config patch. Requires ``device:read``.
Replace a fleet device group's config patch. Requires ``device:update``.
List all API keys for the workspace. Secret key values are never returned — keys are represented by their non-secret ``keyId`` handle and a masked ``prefix``. Returns ``{ api_keys, publishable_key }`` where ``publishable_key`` is the workspace's ``rf_<workspaceId>`` key (safe to embed in client-side code).
Get metadata for a single API key by its keyId. Secret values are never returned. The key is identified by its non-secret ``keyId`` handle (not the secret key string).
List the workspace members who may be named as a key's ``owners``. Owners receive the rotation reminder email, so they must be able to roll the key: for a workspace-wide key, members who can create and revoke keys and view the workspace key list; for a folder key, members who can also write every folder it is scoped to. Each must have an account email the platform can send to. Call this before passing ``owners`` to ``api_keys_create``, ``api_keys_update`` or ``api_keys_roll``; the platform rejects uids that are not listed here. Pass ``key_id`` for an existing key, or ``folder_ids`` for one about to be created (omit both for a workspace-wide key). The platform accepts either the ``api-key:create`` or the ``api-key:update`` scope, and the workspace needs the Advanced API Keys plan feature. Returns ``{ members: [{uid, name, email}, ...] }``.
Get the workspace's publishable key (``rf_<workspaceId>``). The publishable key is the non-secret workspace identifier used with Roboflow.js and browser-side inference SDKs. It is browser-safe and cannot manage workspace data or read private resources. It is not a true secret, but it is not powerless: anyone who holds it can run inference and download the workspace's deployed models. Embed it in client-side code as intended; do not treat it as a capability to hand to untrusted parties.
Create a new API key for the workspace. Who can create keys: a credential may create keys only if it is unscoped (full access) or holds the ``api-key:create`` scope; an OAuth token also needs the ``create_api_key`` permission. Always ask for least-privilege ``scopes`` first. When ``scopes`` is omitted the key inherits every scope of the calling credential, so a full-access caller creates a full-access key (it comes back with ``scopes: null``); the dashboard's scoped default does not apply here. Scoped keys, like ``folder_ids``, ``custom_metadata``, ``rotation_due_at`` and ``owners``, need the Advanced API Keys plan feature. Without it the platform answers 403 and this tool says which arguments need it. That is a plan limit, not a permissions problem: tell the user, and do not silently retry without ``scopes``. The only key such a plan can create is unscoped, so create one only after the user agrees to a key with all of the caller's access (and suggest revoking it with ``api_keys_revoke`` once the task is done). For browser or client-side inference, the publishable key from ``api_keys_get_publishable`` may be enough and needs no secret. Scopes are stored as explicit leaf scopes — a section name or ``role:`` preset is expanded to its current leaves, so a key never auto-gains an ability added to that group later (add new scopes explicitly when needed). The secret ``key`` value is returned ONCE in the response and cannot be retrieved again. Store it immediately in a ``.gitignore``'d ``.env`` file (e.g. ``ROBOFLOW_API_KEY=rf_...``). Never echo it in logs, code comments, or tool output. Rotation reminders: set ``rotation_due_at`` to have the platform email the key's ``owners`` 15 days before the key is due; without a date no reminder is sent. Returns ``{ key_id, key, name, scopes, folder_ids, protected, rotation_due_at, owners, publishable_key }``. ``key_id`` is the non-secret handle used in all subsequent management calls.
Update the name, scopes, custom_metadata or rotation schedule of an API key. Only fields you provide are sent; omitted fields are left unchanged. Omitting ``name`` leaves the name unchanged; omitting ``custom_metadata`` leaves the metadata unchanged. Omitting ``scopes`` leaves the key's scopes unchanged, while passing a list replaces them entirely (including ``role:<name>`` presets). To widen a scoped key back to full access, pass ``["role:owner"]`` (subject to the usual subset rules and the Advanced API Keys feature). ``rotation_due_at`` sets the date the platform reminds the ``owners`` about, 15 days ahead; an empty string clears it. ``owners`` replaces the list with members who can roll the key (see ``api_keys_owner_candidates``). To protect or disable a key use ``api_keys_protect`` or ``api_keys_disable``. Protection cannot be changed here (unprotecting is dashboard-only). Returns the updated masked key metadata.
Mark an API key as protected so it cannot be revoked or disabled. Protection is one-way from the API: a protected key can only be unprotected in the Roboflow dashboard at ``app.roboflow.com/settings/api``. The API, CLI, and MCP cannot unprotect a key, so there is deliberately no ``api_keys_unprotect`` tool. Returns the updated masked key metadata.
Disable (or re-enable) an API key without revoking it. A disabled key is inactive and will be rejected by the platform until re-enabled. Protected keys cannot be disabled; disabling requires the Advanced API Keys plan feature, so the specific error returned depends on the workspace. A key that backs a dedicated deployment cannot be disabled from here either (the deployment would be paused): to rotate such a key use ``api_keys_roll``, which moves the deployment onto the replacement key. Returns the updated masked key metadata.
Permanently revoke (delete) an API key. Revocation is irreversible — the key can never be recovered or re-enabled. Protected keys cannot be revoked; an admin must first unprotect the key in the Roboflow dashboard at ``app.roboflow.com/settings/api``. A key that backs a dedicated deployment cannot be revoked from here either (the deployment would be paused): to rotate such a key — for example after a leak — use ``api_keys_roll``, which moves the deployment onto the replacement key. Returns ``{ status, key_id }``.
Roll (rotate) an API key: revoke it and mint a replacement in one step. This is the rotation path for a leaked or compromised key. The replacement keeps the old key's whole identity — name, scopes, folders, protection and disabled state — so nothing the key was allowed to do changes; only the secret does. Any dedicated deployment anchored on the old key is moved onto the replacement automatically, which is why roll is allowed where ``api_keys_disable`` and ``api_keys_revoke`` refuse. The old secret stops working immediately and its ``key_id`` is retired; the roll cannot be undone. Protected keys cannot be rolled (unprotect in the dashboard first), and a disabled key that backs a dedicated deployment must be re-enabled before it can be rolled. The new secret ``key`` is returned ONCE and cannot be retrieved again. Store it immediately in a ``.gitignore``'d ``.env`` file and update every consumer of the old key; never echo it in logs or tool output. The replacement stays on the old key's rotation schedule (due date shifted by the old key's interval, same owners) unless ``rotation_due_at`` or ``owners`` sets it. Returns ``{ key_id, key, name, scopes, folder_ids, protected, disabled, rotation_due_at, owners, revoked_key_id }``. ``key_id`` is the new key's non-secret handle; ``revoked_key_id`` is the handle that was rolled.
List the workspace folders visible to this credential. Returns ``{ folders: [{id, name, parent_id, child_ids, projects, external_id}, ...] }``. ``projects`` holds the URLs of the projects in the folder; ``parent_id`` and ``child_ids`` describe the folder tree. ``child_ids`` names only folders this credential can list, but ``parent_id`` is the platform's value, so the top of a folder-scoped credential's subtree can point at a folder that is not in the list. A folder-scoped credential sees only its own folders. An empty list means no folders are visible to this credential, not necessarily that the workspace has none. Pass ``folder_id`` to fetch a single folder; an unknown id also yields an empty list.
List the workspace's scheduled, live and past announcements, newest start first. Returns ``{ announcements: [{id, message, starts_at, ends_at, timezone, status, lifecycle, revision, created_at, created_via, updated_at, updated_via}], next_cursor }``. ``status`` is ``active`` (showing now), ``upcoming`` or ``previous``. ``next_cursor`` is null on the last page. Deleted announcements are not listed. Requires permission to manage workspace announcements and a plan that includes them; otherwise the platform answers 403.
Schedule a banner announcement that every member of the workspace sees. Confirm the text and window with the user before calling: the banner reaches everyone in the workspace as soon as its window opens. Times are ISO-8601 with an explicit offset, e.g. ``2026-09-03T09:00:00-04:00``. A window lasts 5 minutes to 365 days and may not overlap another announcement; an overlap fails with 409 and names the conflicting announcement and its window, so pick a free window or update the other announcement. Returns ``{ announcement, start_at_clamped, dismissals_reset }``. When ``start_at_clamped`` is true the start was in the past and was moved to now; tell the user.
Change an announcement's text, window or display timezone. Only the fields you pass change; pass at least one. The previous text is replaced and cannot be recovered. The same window rules as workspace_announcements_create apply, including the 409 on overlap. Returns ``{ announcement, start_at_clamped, dismissals_reset }``. Changing the message or start shows the banner again to everyone who dismissed it (``dismissals_reset`` true); changing only the end or timezone does not. Tell the user when either flag is true.
Delete an announcement. A live banner disappears for everyone right away. The announcement drops out of workspace_announcements_list and cannot be restored through MCP. An unknown or already deleted id answers 404.
Query production vision events for a use case, with filters and pagination. This is the primary tool for answering questions like "what safety alerts fired in the last week?" or "how many failed quality checks did device X report yesterday?". Combine ``start_time``/``end_time`` with ``event_types`` for time-bounded reporting, then page with ``cursor``. Returns ``{events, nextCursor, hasMore, lookbackDays}``. ``hasMore`` is true when more pages exist; pass ``nextCursor`` back as ``cursor`` to fetch them. ``lookbackDays`` is the workspace's maximum history window, queries cannot see events older than that regardless of ``start_time``. Each event generally carries ``eventId``, ``eventType``, ``timestamp``, ``eventData`` (type-specific), ``images`` with their detections, and event-level ``customMetadata``. Each image may also carry its own ``metadata``, a flat map of per-image keys (string, number, or boolean values) returned as ``images[].metadata``. Fields such as ``deviceId``, ``streamId``, ``workflowId``, and ``displayImagePosition`` appear only when set on the event. The use case is not echoed back per event because the result is already scoped to the ``use_case_id`` you passed, so don't rely on a ``useCaseId``/``solution`` field being present on each event. To run a search someone saved in the Search tab, pass its id as ``saved_filter_id`` (list them with ``vision_events_saved_filters_list``) instead of filters; only ``limit`` and ``cursor`` can go with it. Saved filters exclude ``operator_feedback`` events, as the Search tab does. To filter on metadata, discover the keys first: ``vision_events_custom_metadata_schema_get`` lists the event-level keys for ``customMetadataFilters`` and ``vision_events_image_metadata_schema_get`` lists the per-image keys for ``imageMetadataFilters``. Pass either list through ``additional_filters``. An ``imageMetadataFilters`` item matches an event when any of its images satisfies it, while ``neq``/``not_in`` match only when none of its images does.
List the vision-event use cases in the workspace. Use cases are the logical buckets events are grouped under; every query is scoped to one. Call this first to discover the ``id`` values to pass as ``use_case_id`` to ``vision_events_query``. Returns ``{useCases, lookbackDays}``. Each use case reliably carries ``id`` (the value to pass as ``use_case_id`` elsewhere), ``name``, and ``status``; other fields (timestamps, and any per-use-case counts or event-type summaries) may or may not be present depending on the workspace, so treat them as optional rather than guaranteed.
Get the custom-metadata schema discovered for a use case. Custom metadata is arbitrary key/value data attached to events at ingestion time. This returns the fields seen so far and their value types, which is what you need to build ``customMetadataFilters`` for ``vision_events_query``. Keys attached to individual images (``images[].metadata``) are listed separately by ``vision_events_image_metadata_schema_get``. Returns ``{useCaseId, fields}`` where ``fields`` maps each field name to the value types observed for it (string, number, and/or boolean).
Get the per-image metadata schema discovered for a use case. Per-image metadata is key/value data attached to an individual image inside an event (for example the camera or station that captured it), as opposed to the event-level ``customMetadata`` covered by ``vision_events_custom_metadata_schema_get``. In ``vision_events_query`` results it appears on each image as ``images[].metadata``. This returns the keys seen so far and their value types, which is what you need to build ``imageMetadataFilters`` for ``vision_events_query``. Returns ``{useCaseId, fields}`` where ``fields`` maps each key to the value types observed for it (string, number, and/or boolean). A key holding date-like strings may instead report a raw storage type such as ``DateTime64(9)``; such a key is not returned in ``images[].metadata`` and cannot be used in ``imageMetadataFilters``.
Create a new vision-event use case. Use cases are the buckets that incoming events are grouped under. Returns ``{id, name}``; use the returned ``id`` as ``use_case_id`` when querying or ingesting events for this bucket.
Rename an existing vision-event use case. Only the display name changes; the ``id`` and all associated events are preserved. Returns ``{id, name}``.
Archive a vision-event use case. Sets the use case to ``inactive``: it is hidden from the default ``active`` listing and incoming events for it are rejected at ingestion, so this can disrupt a live pipeline. The use case and its existing events are preserved and it can be restored with ``vision_events_use_case_unarchive``. Returns ``{success}``.
Restore a previously archived vision-event use case. The reverse of ``vision_events_use_case_archive``; the use case returns to the default ``active`` listing. Returns ``{success}``.
List the filters saved for a use case. Saved filters are named Search-tab filter sets, shared with the whole workspace. Run one with ``vision_events_query`` and its ``saved_filter_id``. Returns ``{savedFilters}``, sorted by name. Each carries ``id``, ``name``, ``filters`` (the chips, in the shape described on ``vision_events_saved_filter_create``), ``createdBy`` and ``updatedBy`` (user ids), and ``createdAt``/``updatedAt``.
Get one saved filter. Returns ``{savedFilter}``.
Save a named filter for a use case, shared with the whole workspace. Everyone in the workspace sees it in the use case's Search tab. Needs the Create Vision Events permission. A use case holds at most 100 saved filters; a duplicate name or a full use case is refused with a 409. Returns ``{savedFilter}``.
Rename a saved filter, save over its filters, or both. Saving over replaces the filter's chips for everyone in the workspace and needs ``vision-events:write`` with the Create Vision Events permission; it works on any saved filter, and changing someone else's is recorded in the workspace audit log. Renaming needs the person who saved the filter, or ``vision-events:manage`` with the Manage Vision Events permission. A plain API key is never the person who saved a filter, so with one, renaming needs ``vision-events:manage``. Returns ``{savedFilter}``.
Delete a saved filter for everyone in the workspace. Allowed for the person who saved it, or with ``vision-events:manage`` and the Manage Vision Events permission. A plain API key is never the person who saved a filter, so with one this needs ``vision-events:manage``. Events are not affected. Returns ``{success}``.
Search Roboflow Universe for datasets or models. With result_type 'model', each result lists its runnable modelVersions, each with the exact model_id to deploy or run, older versions included. The query supports operators mixed with free-text: - Add 'model' to only return datasets with trained models - 'class:helmet,person' filters by class names - 'images>500' filters by image count (also >=, <, <=) - 'sort:stars' sorts results (stars, images, downloads, views, updated) - 'object detection' filters by project type - 'updated:30d' filters by recency Example: 'fire smoke class:fire,smoke images>200 model sort:stars'
List datasource (cloud-bucket mirror) configurations in the workspace. Returns ``{ datasources }`` where each entry is trimmed to ``{id, name, credentialId, validated, requireVpce, latestJob}``. Use ``datasource_get`` for a single config's full detail.
Get full detail for a single datasource, including its bucket, mirror rules, and latest job summary.
Check that Roboflow can access the datasource's bucket. Returns ``{checks, errors}`` where ``checks`` reports whether ``listFiles``/``headFile``/``getFile`` succeeded plus a per-mirror ``headGlobFile`` result. Use it to self-diagnose a misconfigured credential or bucket before triggering a run.
Get the status and statistics of a single datasource mirror run. Poll this with a ``batchId`` from ``datasource_trigger`` to track a run. Returns the job's ``status`` (running/completed/failed), per-stage ``counters`` (enqueued/completed/failed), any ``errors``, and timestamps (``startedAt``/``completedAt``/``lastSyncedAt``).
Create a datasource that mirrors a cloud bucket into your workspace. Returns the created datasource {id}. Nothing is mirrored until you call datasource_trigger (or a schedule fires). A run may overwrite imported images or metadata and remove mirrored images whose source disappears. Alternative: to only run a model/Workflow over the files and get results out, WITHOUT importing them into Roboflow, use batch processing instead (start with batch_processing_guide). Mirroring also composes with it: imported files become Asset Library images, and bulk predictions over them run as Asset Library jobs (batch_processing_asset_library_job_create). AWS/S3 assisted setup: use the bucket and profile chosen by the user. Only query that account for details needed to configure the selected bucket. - Bucket: Ask the user which bucket to connect. Only inspect that bucket's object paths when the user asks for help choosing mirror rules; do not enumerate other profiles, buckets, or their contents. - Region: For AWS/S3, look up the chosen bucket's region with `aws s3api get-bucket-location --bucket <bucket-name> --profile <profile>` if the user wants assistance (`null`/`None` means us-east-1). Use the AWS profile the user selected. If it is unclear which profile to use, ask the user before querying their AWS account. These commands only read non-secret metadata for the selected account and bucket; never read ~/.aws/credentials or pass secret values yourself. - Credential: When a new AWS credential must be created, before handing off to the Roboflow form: resolve the AWS account for the profile in use with `aws sts get-caller-identity --profile <p>` (reads non-secret identity only), then give the user an account-scoped console deep-link so they land in the right account. Sign in at https://<accountId>.signin.aws.amazon.com/console, then for an IAM credential create an IAM user at https://console.aws.amazon.com/iam/home#/users/create, or for an AssumeRole credential create an IAM role at https://console.aws.amazon.com/iam/home#/roles/create (trusting the Roboflow principal from the prerequisites docs). Collect the resulting access keys (IAM) or role ARN (AssumeRole) and enter them in the Roboflow form.
Update a datasource. Only the fields you pass are changed. To replace the bucket, pass ``bucket_type``, ``bucket_name`` and ``region`` together (``endpoint`` is optional and only applied with them). Returns the updated datasource.
Delete a datasource configuration. Does not delete already-mirrored images.
Start a mirror run for a datasource. This kicks off a job that ingests bucket contents into your workspace. Depending on the saved mirror rules, it can overwrite imported images or metadata and remove images whose source objects disappeared. It can consume compute/storage credits. Returns ``{batchIds}`` for the run(s) that were started. Use ``datasource_validate`` first if you are unsure the bucket is reachable.
Connect a cloud bucket end to end in one call: reuse or create a credential, create the datasource, validate it, and start the first mirror run. A run can overwrite imported images or metadata and remove mirrored images whose source disappeared. Alternative: to only run a model/Workflow over the files and get results out, WITHOUT importing them into Roboflow, use batch processing instead (start with batch_processing_guide). Mirroring also composes with it: imported files become Asset Library images, and bulk predictions over them run as Asset Library jobs (batch_processing_asset_library_job_create). Drive the conversation in this order, and do NOT bring up credentials until the bucket is settled: 1. Pick the bucket FIRST. Ask the user which bucket to connect, confirm its region, and settle which objects to mirror (mirror_configs). Don't mention credentials yet. 2. Credential, only after the bucket is chosen. Prefer reusing one the user already has (check credentials_list and pass its credential_id). Only if none fits, create a new one dedicated to Roboflow by passing credential_name + credential_type. Secrets are never entered in chat: creating a new credential returns manual_entry_required with a url to the Roboflow app, a docs_url, and (for AWS) an aws_setup deep-link. A dedicated, least-privilege credential scoped to this bucket is recommended over reusing personal keys (IAM user with read-only or bucket-scoped access, or an IAM role that trusts Roboflow via AssumeRole). 3. Call this once with the bucket and credential to create, validate, and (when trigger is true) run it. AWS/S3 assisted setup: use the bucket and profile chosen by the user. Only query that account for details needed to configure the selected bucket. - Bucket: Ask the user which bucket to connect. Only inspect that bucket's object paths when the user asks for help choosing mirror rules; do not enumerate other profiles, buckets, or their contents. - Region: For AWS/S3, look up the chosen bucket's region with `aws s3api get-bucket-location --bucket <bucket-name> --profile <profile>` if the user wants assistance (`null`/`None` means us-east-1). Use the AWS profile the user selected. If it is unclear which profile to use, ask the user before querying their AWS account. These commands only read non-secret metadata for the selected account and bucket; never read ~/.aws/credentials or pass secret values yourself. - Credential: When a new AWS credential must be created, before handing off to the Roboflow form: resolve the AWS account for the profile in use with `aws sts get-caller-identity --profile <p>` (reads non-secret identity only), then give the user an account-scoped console deep-link so they land in the right account. Sign in at https://<accountId>.signin.aws.amazon.com/console, then for an IAM credential create an IAM user at https://console.aws.amazon.com/iam/home#/users/create, or for an AssumeRole credential create an IAM role at https://console.aws.amazon.com/iam/home#/roles/create (trusting the Roboflow principal from the prerequisites docs). Collect the resulting access keys (IAM) or role ARN (AssumeRole) and enter them in the Roboflow form. The mirror run only starts when trigger is true AND validation reports no errors; triggering consumes credits. Returns {credentialId, credentialCreated, datasourceId, validation, triggered, batchIds?}. If a new credential was created but a later step failed, a partial status is returned with the credentialId so it can be cleaned up with credentials_delete.
List cloud-storage credentials in the workspace. Secrets are masked server-side, so only non-sensitive fields (id, type, name, description) come back. Returns ``{ credentials }``.
Delete a credential. Datasources still referencing it will fail to run.
Get a Roboflow app link to set up an AWS S3 storage credential. This tool does not create a credential. It returns ``manual_entry_required`` with a ``url`` for the Roboflow form, a ``docs_url`` for prerequisites, and ``aws_setup`` guidance for the correct AWS account. Only the non-secret name, credential_type, and description are passed here. The user enters AWS access keys or role details in the Roboflow app, never in chat or this tool. IAM uses AWS access keys; AssumeRole uses an AWS IAM role. Recommend a credential dedicated to Roboflow with read-only or bucket-scoped access. After the user completes the form, use credentials_list to find its id.
List soft-deleted items currently in the workspace Trash. Deleted projects, versions, workflows, and trainings stay in the Trash for 30 days before permanent removal. Use the returned item type and document id with the matching ``trash_restore_*`` tool to recover an item.
Restore a soft-deleted project from the workspace Trash. Undoes ``projects_delete`` while the project is still within its 30-day retention window.
Restore a soft-deleted dataset version from the workspace Trash. Undoes ``versions_delete`` while the version is still within its 30-day retention window. ``parent_id`` is the parent project's document id.
Restore a soft-deleted workflow from the workspace Trash. Undoes ``workflows_delete`` while the workflow is still within its 30-day retention window.
Restore a soft-deleted training run from the workspace Trash. Undoes ``trainings_delete`` while the training is still within its 30-day retention window.
Poll an async task by id. Poll every 5 seconds; processing may take up to 30 seconds to start. Returns `{ taskId, status, progress, result?, error? }`. `status` is one of `created`, `running`, `completed`, `failed`.
Send product feedback about Roboflow to the Roboflow team. Records a bug report, missing-feature request, UX friction note, or documentation issue against the current workspace. Use when the user wants to report a problem with Roboflow or send feedback. Returns confirmation that the feedback was recorded.
Open the Roboflow annotation editor for one image. Use this when a person needs to inspect or edit image annotations visually. Changes are saved only when the person chooses Save in the widget. For usage guidance, read skill://roboflow-apps/annotation-editor/SKILL.md.
Reload the editor snapshot and revision after a save or conflict.
Save the user's annotation edits using the loaded group revision. A conflict requires reloading and reconciling edits. Never blindly retry.
Show the project's live endpoint on one workspace image or video, in an interactive player. Use this when the user wants to see what the project's model finds on their own media. Each call runs inference and spends credits; a video runs as a job on a clip of 60 s at most. Only the counts per class come back here; the user filters by confidence and class in the widget, and on SAM 3 projects can change the classes and run again there. A project that never had an endpoint gets one (its base workflow) before the preview runs. For usage guidance, read skill://roboflow-apps/model-preview/SKILL.md.
Show a saved Workflow's results on one workspace image or video, in an interactive player. Use this when the user wants to see a Workflow's output images, values and JSON on their own media. Each call runs the Workflow and spends credits; a video runs as a job on a clip of 60 s at most. Sink blocks (webhooks, uploads, notifications) run unless disable_sinks is true. Only Workflows with exactly one image input can be previewed; the platform refuses others before running, and the refusal is returned. For usage guidance, read skill://roboflow-apps/workflow-preview/SKILL.md.
Run a preview again from its rerunArguments, with the classes the user changed.
Read a preview job with its segments and results; every call signs its urls again.
Stop a preview job. It cannot resume; a new run starts a new job.
A fresh signed url for the preview's source video, when the widget reopens after it expired.
One endpoint, the same key, whichever client you use.
~/Library/Application Support/Claude/claude_desktop_config.json (Mac) · %APPDATA%\Claude\claude_desktop_config.json (Windows)
Replace API_KEY with your own key.
Already have an "mcpServers" section in your config? Just add the server entry inside it.
Discovery, routing, credentials, tool scoping and execution logs all happen at the gateway→connections stay ACTIVE with no work from you
Roboflow MCP runs through a gateway that holds the credentials, scopes the access and records every call.
Managed auth, hosted MCP servers, and every Roboflow MCP tool your agent needs.
Free to start.
Find slots across four interviewer calendars, book the events, and email the candidate a clean schedule with links and interviewer one pagers.