Improve search_key/error_code API docs and reorganize Fern sections (#SKY-7884) (#4740)

Co-authored-by: Suchintan Singh <suchintan@skyvern.com>
This commit is contained in:
Suchintan
2026-02-13 00:30:46 -05:00
committed by GitHub
parent cc4a8b83cc
commit c1272b3701
2 changed files with 123 additions and 31 deletions

View File

@@ -176,15 +176,20 @@ navigation:
hidden: true
- GET /v1/runs/{run_id}/timeline
- section: Workflows
contents:
- GET /v1/workflows
- POST /v1/workflows
- GET /v1/workflows/{workflow_permanent_id}
- GET /v1/workflows/{workflow_permanent_id}/versions
- POST /v1/workflows/{workflow_id}
- POST /v1/workflows/{workflow_id}/delete
- section: Workflow Runs
contents:
- POST /v1/run/workflows
- GET /v1/workflows/runs
- GET /v1/runs/{run_id}
- POST /v1/runs/{run_id}/cancel
- POST /v1/runs/{run_id}/retry_webhook
- GET /v1/workflows
- POST /v1/workflows
- POST /v1/workflows/{workflow_id}
- POST /v1/workflows/{workflow_id}/delete
- GET /v1/runs/{run_id}/timeline
- section: Browser Sessions
contents:
@@ -202,6 +207,7 @@ navigation:
contents:
- POST /v1/credentials
- GET /v1/credentials/{credential_id}
- POST /v1/credentials/{credential_id}/update
- POST /v1/credentials/{credential_id}/delete
- GET /v1/credentials
- POST /v1/credentials/totp

View File

@@ -333,7 +333,7 @@ async def run_task(
@base_router.post(
"/run/workflows",
tags=["Workflows"],
tags=["Workflow Runs"],
openapi_extra={
"x-fern-sdk-method-name": "run_workflow",
"x-fern-examples": [
@@ -438,7 +438,7 @@ async def run_workflow(
@base_router.get(
"/runs/{run_id}",
tags=["Agent", "Workflows"],
tags=["Agent", "Workflow Runs"],
response_model=RunResponse,
description="Get run information (task run, workflow run)",
summary="Get a run by id",
@@ -480,7 +480,7 @@ async def get_run(
@base_router.post(
"/runs/{run_id}/cancel",
tags=["Agent", "Workflows"],
tags=["Agent", "Workflow Runs"],
openapi_extra={
"x-fern-sdk-method-name": "cancel_run",
"x-fern-examples": [
@@ -1444,7 +1444,7 @@ async def get_run_artifacts(
@base_router.post(
"/runs/{run_id}/retry_webhook",
tags=["Agent"],
tags=["Agent", "Workflow Runs"],
openapi_extra={
"x-fern-sdk-method-name": "retry_run_webhook",
"x-fern-examples": [
@@ -1477,7 +1477,7 @@ async def retry_run_webhook(
@base_router.get(
"/runs/{run_id}/timeline",
tags=["Agent", "Workflows"],
tags=["Agent", "Workflow Runs"],
response_model=list[WorkflowRunTimeline],
openapi_extra={
"x-fern-sdk-method-name": "get_run_timeline",
@@ -1992,7 +1992,13 @@ async def get_runs(
status: Annotated[list[WorkflowRunStatus] | None, Query()] = None,
search_key: str | None = Query(
None,
description="Search runs by run ID, parameter key, parameter description, run parameter value, or extra HTTP headers.",
description=(
"Case-insensitive substring search across: workflow run ID, "
"parameter key, parameter description, run parameter value, "
"and extra HTTP headers. A run is returned if any of these fields match. "
"Soft-deleted parameter definitions are excluded from key/description matching."
),
examples=["login_url", "credential_value", "wr_abc123"],
),
) -> Response:
analytics.capture("skyvern-oss-agent-runs-get")
@@ -2205,11 +2211,32 @@ async def run_workflow_legacy(
@base_router.get(
"/workflows/runs",
response_model=list[WorkflowRun],
tags=["Workflows"],
tags=["Workflow Runs"],
description=(
"List workflow runs across all workflows for the current organization. "
"Results are paginated and can be filtered by status, search key, and error code. "
"All filters are combined with AND logic."
"List workflow runs across all workflows for the current organization.\n\n"
"Results are paginated and can be filtered by **status**, **search_key**, and **error_code**. "
"All filters are combined with **AND** logic — a run must match every supplied filter to be returned.\n\n"
"### search_key\n\n"
"A case-insensitive substring search that matches against **any** of the following fields:\n\n"
"| Searched field | Description |\n"
"|---|---|\n"
"| `workflow_run_id` | The unique run identifier (e.g. `wr_123…`) |\n"
"| Parameter **key** | The `key` of any workflow parameter definition associated with the run |\n"
"| Parameter **description** | The `description` of any workflow parameter definition |\n"
"| Run parameter **value** | The actual value supplied for any parameter when the run was created |\n"
"| `extra_http_headers` | Extra HTTP headers attached to the run (searched as raw JSON text) |\n\n"
"Soft-deleted parameter definitions are excluded from key/description matching. "
"A run is returned if **any** of the fields above contain the search term.\n\n"
"### error_code\n\n"
"An **exact-match** filter against the `error_code` field inside each task's `errors` JSON array. "
"A run matches if **any** of its tasks contains an error object with a matching `error_code` value. "
"Error codes are user-defined strings set during workflow execution "
"(e.g. `INVALID_CREDENTIALS`, `LOGIN_FAILED`, `CAPTCHA_DETECTED`).\n\n"
"### Combining filters\n\n"
"All query parameters use AND logic:\n"
"- `?status=failed` — only failed runs\n"
"- `?status=failed&error_code=LOGIN_FAILED` — failed runs **and** have a LOGIN_FAILED error\n"
"- `?status=failed&error_code=LOGIN_FAILED&search_key=prod_credential` — all three conditions must match"
),
summary="List workflow runs",
openapi_extra={
@@ -2241,14 +2268,22 @@ async def get_workflow_runs(
search_key: str | None = Query(
None,
max_length=500,
description="Search runs by run ID, parameter key, parameter description, run parameter value, or extra HTTP headers.",
examples=["login_url", "credential_value"],
description=(
"Case-insensitive substring search across: workflow run ID, "
"parameter key, parameter description, run parameter value, "
"and extra HTTP headers. A run is returned if any of these fields match. "
"Soft-deleted parameter definitions are excluded from key/description matching."
),
examples=["login_url", "credential_value", "wr_abc123"],
),
error_code: str | None = Query(
None,
max_length=500,
description="Filter runs by user-defined error code stored in task errors. "
"Matches against the error_code field in the task errors JSON array.",
description=(
"Exact-match filter on the error_code field inside each task's errors JSON array. "
"A run matches if any of its tasks contains an error with a matching error_code. "
"Error codes are user-defined strings set during workflow execution."
),
examples=["INVALID_CREDENTIALS", "LOGIN_FAILED", "CAPTCHA_DETECTED"],
),
current_org: Organization = Depends(org_auth_service.get_current_org),
@@ -2256,13 +2291,22 @@ async def get_workflow_runs(
"""
List workflow runs across all workflows for the current organization.
Results are paginated and can be filtered by status, search key, and error code.
All filters are combined with AND logic.
All filters (**status**, **search_key**, **error_code**) are combined with AND logic.
**search_key** performs a case-insensitive substring match across:
- `workflow_run_id` — the unique run identifier
- Parameter **key** and **description** from workflow parameter definitions (soft-deleted parameters excluded)
- Run parameter **value** — the actual value supplied when the run was created
- `extra_http_headers` — searched as raw JSON text
**error_code** performs an exact match against the `error_code` field in the `errors`
JSON array on each task. A run matches if *any* of its tasks has a matching error code.
**Examples:**
- All failed runs: `?status=failed`
- Failed runs with a specific error: `?status=failed&error_code=INVALID_CREDENTIALS`
- Runs matching a parameter value: `?search_key=https://example.com`
- Runs matching a run ID: `?search_key=wr_abc123`
- Combined: `?status=failed&error_code=LOGIN_FAILED&search_key=my_credential`
"""
analytics.capture("skyvern-oss-agent-workflow-runs-get")
@@ -2280,6 +2324,19 @@ async def get_workflow_runs(
"/workflows/{workflow_id}/runs",
response_model=list[WorkflowRun],
tags=["agent"],
description=(
"List runs for a specific workflow.\n\n"
"Supports filtering by **status**, **search_key**, and **error_code**. "
"All filters are combined with **AND** logic.\n\n"
"### search_key\n\n"
"Case-insensitive substring search across: workflow run ID, "
"parameter key, parameter description, run parameter value, "
"and extra HTTP headers. Soft-deleted parameter definitions are excluded.\n\n"
"### error_code\n\n"
"Exact-match filter on the `error_code` field inside each task's `errors` JSON array. "
"A run matches if any of its tasks contains an error with a matching `error_code`."
),
summary="List runs for a workflow",
openapi_extra={
"x-fern-sdk-method-name": "get_workflow_runs_by_id",
},
@@ -2291,33 +2348,51 @@ async def get_workflow_runs(
)
async def get_workflow_runs_by_id(
workflow_id: str,
page: int = Query(1, ge=1),
page_size: int = Query(10, ge=1),
status: Annotated[list[WorkflowRunStatus] | None, Query()] = None,
page: int = Query(1, ge=1, description="Page number for pagination."),
page_size: int = Query(10, ge=1, description="Number of runs to return per page."),
status: Annotated[list[WorkflowRunStatus] | None, Query(description="Filter by one or more run statuses.")] = None,
search_key: str | None = Query(
None,
max_length=500,
description="Search runs by run ID, parameter key, parameter description, run parameter value, or extra HTTP headers.",
description=(
"Case-insensitive substring search across: workflow run ID, "
"parameter key, parameter description, run parameter value, "
"and extra HTTP headers. A run is returned if any of these fields match. "
"Soft-deleted parameter definitions are excluded from key/description matching."
),
examples=["login_url", "credential_value", "wr_abc123"],
),
error_code: str | None = Query(
None,
max_length=500,
description="Filter runs by user-defined error code stored in task errors. "
"Matches against the error_code field in the task errors JSON array.",
description=(
"Exact-match filter on the error_code field inside each task's errors JSON array. "
"A run matches if any of its tasks contains an error with a matching error_code. "
"Error codes are user-defined strings set during workflow execution."
),
examples=["INVALID_CREDENTIALS", "LOGIN_FAILED", "CAPTCHA_DETECTED"],
),
current_org: Organization = Depends(org_auth_service.get_current_org),
) -> list[WorkflowRun]:
"""
Get workflow runs for a specific workflow permanent id.
List runs for a specific workflow permanent id.
Supports filtering by status, parameter search, and error code. All filters
are combined with AND logic.
All filters (**status**, **search_key**, **error_code**) are combined with AND logic.
**search_key** performs a case-insensitive substring match across:
- `workflow_run_id` — the unique run identifier
- Parameter **key** and **description** from workflow parameter definitions (soft-deleted parameters excluded)
- Run parameter **value** — the actual value supplied when the run was created
- `extra_http_headers` — searched as raw JSON text
**error_code** performs an exact match against the `error_code` field in the `errors`
JSON array on each task. A run matches if *any* of its tasks has a matching error code.
**Examples:**
- All failed runs: `?status=failed`
- Failed runs with a specific error: `?status=failed&error_code=INVALID_CREDENTIALS`
- Runs matching a parameter value: `?search_key=https://example.com`
- Runs matching a run ID: `?search_key=wr_abc123`
- Combined: `?status=failed&error_code=LOGIN_FAILED&search_key=my_credential`
"""
analytics.capture("skyvern-oss-agent-workflow-runs-get")
@@ -2487,9 +2562,20 @@ async def get_workflows(
only_templates: bool = Query(False),
search_key: str | None = Query(
None,
description="Unified search across workflow title, folder name, and parameter metadata (key, description, default_value).",
description=(
"Case-insensitive substring search across: workflow title, folder name, "
"and parameter metadata (key, description, default_value). "
"A workflow is returned if any of these fields match. "
"Soft-deleted parameter definitions are excluded. "
"Takes precedence over the deprecated `title` parameter."
),
examples=["my_workflow", "login_url", "production"],
),
title: str = Query(
"",
deprecated=True,
description="Deprecated: use search_key instead. Falls back to title-only search if search_key is not provided.",
),
title: str = Query("", deprecated=True, description="Deprecated: use search_key instead."),
folder_id: str | None = Query(None, description="Filter workflows by folder ID"),
status: Annotated[list[WorkflowStatus] | None, Query()] = None,
current_org: Organization = Depends(org_auth_service.get_current_org),