from retab import Retab
client = Retab()
# Rename only.
workflow_eval = client.workflows.evals.update(
eval_id="wfnodeeval_hsLEQiM61ez9Piv147MWk",
name="Q1 invoice — vendor name check",
)
# Replace the assertion.
workflow_eval = client.workflows.evals.update(
eval_id="wfnodeeval_hsLEQiM61ez9Piv147MWk",
assertion={
"target": {"output_handle_id": "output-json-0", "path": "vendor.name"},
"condition": {"kind": "matches_regex", "pattern": r"^Acme.*"},
},
)
# Re-capture inputs from a different run.
workflow_eval = client.workflows.evals.update(
eval_id="wfnodeeval_hsLEQiM61ez9Piv147MWk",
source={
"type": "run_step",
"run_id": "wfrun_new789",
"step_id": "block_extract_invoice",
},
)
import { Retab } from "@retab/node";
const client = new Retab({ apiKey: process.env.RETAB_API_KEY });
const renamed = await client.workflows.evals.update("wfnodeeval_hsLEQiM61ez9Piv147MWk", "Q1 invoice — vendor name check");
const reAsserted = await client.workflows.evals.update("wfnodeeval_hsLEQiM61ez9Piv147MWk", undefined, {
target: { outputHandleId: "output-json-0", path: "vendor.name" },
condition: { kind: "matches_regex", pattern: "^Acme.*" },
});
package main
import (
"context"
"log"
retab "github.com/retab-dev/retab/clients/go"
)
func ptr[T any](v T) *T { return &v }
func main() {
ctx := context.Background()
client, err := retab.NewClient("")
if err != nil {
log.Fatal(err)
}
evalID := "wfnodeeval_hsLEQiM61ez9Piv147MWk"
// Rename only.
if _, err := client.Workflows.Evals.Update(ctx, evalID, &retab.WorkflowEvalsUpdateParams{
Name: ptr("Q1 invoice — vendor name check"),
}); err != nil {
log.Fatal(err)
}
// Replace the assertion.
if _, err := client.Workflows.Evals.Update(ctx, evalID, &retab.WorkflowEvalsUpdateParams{
Assertion: &retab.AssertionSpec{
Target: retab.OutputTarget{OutputHandleID: "output-json-0", Path: ptr("vendor.name")},
Condition: retab.ConditionFromExistCondition(retab.ExistCondition{Kind: ptr("exists")}),
},
}); err != nil {
log.Fatal(err)
}
// Re-capture inputs from a different run.
if _, err := client.Workflows.Evals.Update(ctx, evalID, &retab.WorkflowEvalsUpdateParams{
Source: ptr(retab.WorkflowEvalSourceFromManualWorkflowEvalSource(retab.ManualWorkflowEvalSource{
Type: ptr("manual"),
})),
}); err != nil {
log.Fatal(err)
}
}
require 'retab'
client = Retab::Client.new(api_key: ENV['RETAB_API_KEY'])
# Rename only.
workflow_eval = client.workflows.evals.update(
eval_id: 'wfnodeeval_hsLEQiM61ez9Piv147MWk',
name: 'Q1 invoice — vendor name check',
)
# Replace the assertion.
workflow_eval = client.workflows.evals.update(
eval_id: 'wfnodeeval_hsLEQiM61ez9Piv147MWk',
assertion: {
target: { output_handle_id: 'output-json-0', path: 'vendor.name' },
condition: { kind: 'matches_regex', pattern: '^Acme.*' },
},
)
# Re-capture inputs from a different run.
workflow_eval = client.workflows.evals.update(
eval_id: 'wfnodeeval_hsLEQiM61ez9Piv147MWk',
source: {
type: 'run_step',
run_id: 'wfrun_new789',
step_id: 'block_extract_invoice',
},
)
use retab::models::{RunStepWorkflowEvalSource, UpdateWorkflowEvalRequest};
use retab::resources::workflow_evals::UpdateParams;
use retab::Retab;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Retab::new(std::env::var("RETAB_API_KEY")?);
let eval_id = "wfnodeeval_hsLEQiM61ez9Piv147MWk";
// Rename only.
let renamed_body = UpdateWorkflowEvalRequest {
name: Some("Q1 invoice — vendor name check".into()),
..Default::default()
};
let _renamed = client
.workflows().evals()
.update(eval_id, UpdateParams::new(renamed_body))
.await?;
// Re-capture inputs from a different run.
let mut source = RunStepWorkflowEvalSource::new("wfrun_new789");
source.step_id = Some("block_extract_invoice".into());
let resource_body = UpdateWorkflowEvalRequest {
source: Some(source.into()),
..Default::default()
};
let _rebound = client
.workflows().evals()
.update(eval_id, UpdateParams::new(resource_body))
.await?;
Ok(())
}
<?php
require 'vendor/autoload.php';
use Retab\Client;
$client = new Client(apiKey: getenv('RETAB_API_KEY'));
$result = $client->workflows()->evals()->update(
evalId: 'eval_abc123',
);
print_r($result);
using Retab;
using RetabClient = Retab.Retab;
var apiKey = Environment.GetEnvironmentVariable("RETAB_API_KEY")!;
var client = new RetabClient(apiKey);
var result = await client.Workflows.Evals.UpdateAsync("eval_abc123", new WorkflowEvalsUpdateOptions());
Console.WriteLine(result);
import com.retab.RetabClient;
import com.retab.workflowevals.WorkflowEvalsApi;
public final class Example {
public static void main(String[] args) throws Exception {
RetabClient client = new RetabClient(System.getenv("RETAB_API_KEY"));
var result = new WorkflowEvalsApi(client).update("eval_abc123", "Invoice Processing", null, null);
System.out.println(result);
}
}
# Rename only
curl -X 'PATCH' \
'https://api.retab.com/v1/workflows/evals/wfnodeeval_hsLEQiM61ez9Piv147MWk' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <your-api-key>' \
-d '{ "name": "Q1 invoice — vendor name check" }'
# Replace the assertion
curl -X 'PATCH' \
'https://api.retab.com/v1/workflows/evals/wfnodeeval_hsLEQiM61ez9Piv147MWk' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <your-api-key>' \
-d '{
"assertion": {
"target": { "output_handle_id": "output-json-0", "path": "vendor.name" },
"condition": { "kind": "matches_regex", "pattern": "^Acme.*" }
}
}'
{
"id": "wfnodeeval_hsLEQiM61ez9Piv147MWk",
"workflow_id": "wf_abc123xyz",
"target": { "type": "block", "block_id": "block_extract_invoice" },
"source": { "type": "manual", "handle_inputs": { "...": "..." } },
"name": "Q1 invoice — vendor name check",
"assertion": { "...": "the new assertion" },
"schema_drift": "none",
"validation_status": "valid",
"latest_run_summary": null,
"created_at": "2026-04-08T14:22:26Z",
"updated_at": "2026-05-01T14:35:00Z"
}
{
"detail": "assertion cannot be null"
}
{
"detail": "Workflow eval not found: wfnodeeval_hsLEQiM61ez9Piv147MWk"
}
Update Workflow Eval
Update a workflow eval.
Identified by eval_id. Send any of name, assertion, or source;
omitted fields are left unchanged. Returns the updated eval.
from retab import Retab
client = Retab()
# Rename only.
workflow_eval = client.workflows.evals.update(
eval_id="wfnodeeval_hsLEQiM61ez9Piv147MWk",
name="Q1 invoice — vendor name check",
)
# Replace the assertion.
workflow_eval = client.workflows.evals.update(
eval_id="wfnodeeval_hsLEQiM61ez9Piv147MWk",
assertion={
"target": {"output_handle_id": "output-json-0", "path": "vendor.name"},
"condition": {"kind": "matches_regex", "pattern": r"^Acme.*"},
},
)
# Re-capture inputs from a different run.
workflow_eval = client.workflows.evals.update(
eval_id="wfnodeeval_hsLEQiM61ez9Piv147MWk",
source={
"type": "run_step",
"run_id": "wfrun_new789",
"step_id": "block_extract_invoice",
},
)
import { Retab } from "@retab/node";
const client = new Retab({ apiKey: process.env.RETAB_API_KEY });
const renamed = await client.workflows.evals.update("wfnodeeval_hsLEQiM61ez9Piv147MWk", "Q1 invoice — vendor name check");
const reAsserted = await client.workflows.evals.update("wfnodeeval_hsLEQiM61ez9Piv147MWk", undefined, {
target: { outputHandleId: "output-json-0", path: "vendor.name" },
condition: { kind: "matches_regex", pattern: "^Acme.*" },
});
package main
import (
"context"
"log"
retab "github.com/retab-dev/retab/clients/go"
)
func ptr[T any](v T) *T { return &v }
func main() {
ctx := context.Background()
client, err := retab.NewClient("")
if err != nil {
log.Fatal(err)
}
evalID := "wfnodeeval_hsLEQiM61ez9Piv147MWk"
// Rename only.
if _, err := client.Workflows.Evals.Update(ctx, evalID, &retab.WorkflowEvalsUpdateParams{
Name: ptr("Q1 invoice — vendor name check"),
}); err != nil {
log.Fatal(err)
}
// Replace the assertion.
if _, err := client.Workflows.Evals.Update(ctx, evalID, &retab.WorkflowEvalsUpdateParams{
Assertion: &retab.AssertionSpec{
Target: retab.OutputTarget{OutputHandleID: "output-json-0", Path: ptr("vendor.name")},
Condition: retab.ConditionFromExistCondition(retab.ExistCondition{Kind: ptr("exists")}),
},
}); err != nil {
log.Fatal(err)
}
// Re-capture inputs from a different run.
if _, err := client.Workflows.Evals.Update(ctx, evalID, &retab.WorkflowEvalsUpdateParams{
Source: ptr(retab.WorkflowEvalSourceFromManualWorkflowEvalSource(retab.ManualWorkflowEvalSource{
Type: ptr("manual"),
})),
}); err != nil {
log.Fatal(err)
}
}
require 'retab'
client = Retab::Client.new(api_key: ENV['RETAB_API_KEY'])
# Rename only.
workflow_eval = client.workflows.evals.update(
eval_id: 'wfnodeeval_hsLEQiM61ez9Piv147MWk',
name: 'Q1 invoice — vendor name check',
)
# Replace the assertion.
workflow_eval = client.workflows.evals.update(
eval_id: 'wfnodeeval_hsLEQiM61ez9Piv147MWk',
assertion: {
target: { output_handle_id: 'output-json-0', path: 'vendor.name' },
condition: { kind: 'matches_regex', pattern: '^Acme.*' },
},
)
# Re-capture inputs from a different run.
workflow_eval = client.workflows.evals.update(
eval_id: 'wfnodeeval_hsLEQiM61ez9Piv147MWk',
source: {
type: 'run_step',
run_id: 'wfrun_new789',
step_id: 'block_extract_invoice',
},
)
use retab::models::{RunStepWorkflowEvalSource, UpdateWorkflowEvalRequest};
use retab::resources::workflow_evals::UpdateParams;
use retab::Retab;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Retab::new(std::env::var("RETAB_API_KEY")?);
let eval_id = "wfnodeeval_hsLEQiM61ez9Piv147MWk";
// Rename only.
let renamed_body = UpdateWorkflowEvalRequest {
name: Some("Q1 invoice — vendor name check".into()),
..Default::default()
};
let _renamed = client
.workflows().evals()
.update(eval_id, UpdateParams::new(renamed_body))
.await?;
// Re-capture inputs from a different run.
let mut source = RunStepWorkflowEvalSource::new("wfrun_new789");
source.step_id = Some("block_extract_invoice".into());
let resource_body = UpdateWorkflowEvalRequest {
source: Some(source.into()),
..Default::default()
};
let _rebound = client
.workflows().evals()
.update(eval_id, UpdateParams::new(resource_body))
.await?;
Ok(())
}
<?php
require 'vendor/autoload.php';
use Retab\Client;
$client = new Client(apiKey: getenv('RETAB_API_KEY'));
$result = $client->workflows()->evals()->update(
evalId: 'eval_abc123',
);
print_r($result);
using Retab;
using RetabClient = Retab.Retab;
var apiKey = Environment.GetEnvironmentVariable("RETAB_API_KEY")!;
var client = new RetabClient(apiKey);
var result = await client.Workflows.Evals.UpdateAsync("eval_abc123", new WorkflowEvalsUpdateOptions());
Console.WriteLine(result);
import com.retab.RetabClient;
import com.retab.workflowevals.WorkflowEvalsApi;
public final class Example {
public static void main(String[] args) throws Exception {
RetabClient client = new RetabClient(System.getenv("RETAB_API_KEY"));
var result = new WorkflowEvalsApi(client).update("eval_abc123", "Invoice Processing", null, null);
System.out.println(result);
}
}
# Rename only
curl -X 'PATCH' \
'https://api.retab.com/v1/workflows/evals/wfnodeeval_hsLEQiM61ez9Piv147MWk' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <your-api-key>' \
-d '{ "name": "Q1 invoice — vendor name check" }'
# Replace the assertion
curl -X 'PATCH' \
'https://api.retab.com/v1/workflows/evals/wfnodeeval_hsLEQiM61ez9Piv147MWk' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <your-api-key>' \
-d '{
"assertion": {
"target": { "output_handle_id": "output-json-0", "path": "vendor.name" },
"condition": { "kind": "matches_regex", "pattern": "^Acme.*" }
}
}'
{
"id": "wfnodeeval_hsLEQiM61ez9Piv147MWk",
"workflow_id": "wf_abc123xyz",
"target": { "type": "block", "block_id": "block_extract_invoice" },
"source": { "type": "manual", "handle_inputs": { "...": "..." } },
"name": "Q1 invoice — vendor name check",
"assertion": { "...": "the new assertion" },
"schema_drift": "none",
"validation_status": "valid",
"latest_run_summary": null,
"created_at": "2026-04-08T14:22:26Z",
"updated_at": "2026-05-01T14:35:00Z"
}
{
"detail": "assertion cannot be null"
}
{
"detail": "Workflow eval not found: wfnodeeval_hsLEQiM61ez9Piv147MWk"
}
assertion: null is rejected explicitly (use Delete Workflow Eval if
you want to remove the eval entirely).
Updating source rebinds where the inputs come from:
{ type: "manual", handle_inputs: ... }— switch to hand-written inputs.{ type: "run_step", run_id: ..., step_id: ... }— re-capture inputs from a different workflow run / step.
WorkflowEval.
from retab import Retab
client = Retab()
# Rename only.
workflow_eval = client.workflows.evals.update(
eval_id="wfnodeeval_hsLEQiM61ez9Piv147MWk",
name="Q1 invoice — vendor name check",
)
# Replace the assertion.
workflow_eval = client.workflows.evals.update(
eval_id="wfnodeeval_hsLEQiM61ez9Piv147MWk",
assertion={
"target": {"output_handle_id": "output-json-0", "path": "vendor.name"},
"condition": {"kind": "matches_regex", "pattern": r"^Acme.*"},
},
)
# Re-capture inputs from a different run.
workflow_eval = client.workflows.evals.update(
eval_id="wfnodeeval_hsLEQiM61ez9Piv147MWk",
source={
"type": "run_step",
"run_id": "wfrun_new789",
"step_id": "block_extract_invoice",
},
)
import { Retab } from "@retab/node";
const client = new Retab({ apiKey: process.env.RETAB_API_KEY });
const renamed = await client.workflows.evals.update("wfnodeeval_hsLEQiM61ez9Piv147MWk", "Q1 invoice — vendor name check");
const reAsserted = await client.workflows.evals.update("wfnodeeval_hsLEQiM61ez9Piv147MWk", undefined, {
target: { outputHandleId: "output-json-0", path: "vendor.name" },
condition: { kind: "matches_regex", pattern: "^Acme.*" },
});
package main
import (
"context"
"log"
retab "github.com/retab-dev/retab/clients/go"
)
func ptr[T any](v T) *T { return &v }
func main() {
ctx := context.Background()
client, err := retab.NewClient("")
if err != nil {
log.Fatal(err)
}
evalID := "wfnodeeval_hsLEQiM61ez9Piv147MWk"
// Rename only.
if _, err := client.Workflows.Evals.Update(ctx, evalID, &retab.WorkflowEvalsUpdateParams{
Name: ptr("Q1 invoice — vendor name check"),
}); err != nil {
log.Fatal(err)
}
// Replace the assertion.
if _, err := client.Workflows.Evals.Update(ctx, evalID, &retab.WorkflowEvalsUpdateParams{
Assertion: &retab.AssertionSpec{
Target: retab.OutputTarget{OutputHandleID: "output-json-0", Path: ptr("vendor.name")},
Condition: retab.ConditionFromExistCondition(retab.ExistCondition{Kind: ptr("exists")}),
},
}); err != nil {
log.Fatal(err)
}
// Re-capture inputs from a different run.
if _, err := client.Workflows.Evals.Update(ctx, evalID, &retab.WorkflowEvalsUpdateParams{
Source: ptr(retab.WorkflowEvalSourceFromManualWorkflowEvalSource(retab.ManualWorkflowEvalSource{
Type: ptr("manual"),
})),
}); err != nil {
log.Fatal(err)
}
}
require 'retab'
client = Retab::Client.new(api_key: ENV['RETAB_API_KEY'])
# Rename only.
workflow_eval = client.workflows.evals.update(
eval_id: 'wfnodeeval_hsLEQiM61ez9Piv147MWk',
name: 'Q1 invoice — vendor name check',
)
# Replace the assertion.
workflow_eval = client.workflows.evals.update(
eval_id: 'wfnodeeval_hsLEQiM61ez9Piv147MWk',
assertion: {
target: { output_handle_id: 'output-json-0', path: 'vendor.name' },
condition: { kind: 'matches_regex', pattern: '^Acme.*' },
},
)
# Re-capture inputs from a different run.
workflow_eval = client.workflows.evals.update(
eval_id: 'wfnodeeval_hsLEQiM61ez9Piv147MWk',
source: {
type: 'run_step',
run_id: 'wfrun_new789',
step_id: 'block_extract_invoice',
},
)
use retab::models::{RunStepWorkflowEvalSource, UpdateWorkflowEvalRequest};
use retab::resources::workflow_evals::UpdateParams;
use retab::Retab;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Retab::new(std::env::var("RETAB_API_KEY")?);
let eval_id = "wfnodeeval_hsLEQiM61ez9Piv147MWk";
// Rename only.
let renamed_body = UpdateWorkflowEvalRequest {
name: Some("Q1 invoice — vendor name check".into()),
..Default::default()
};
let _renamed = client
.workflows().evals()
.update(eval_id, UpdateParams::new(renamed_body))
.await?;
// Re-capture inputs from a different run.
let mut source = RunStepWorkflowEvalSource::new("wfrun_new789");
source.step_id = Some("block_extract_invoice".into());
let resource_body = UpdateWorkflowEvalRequest {
source: Some(source.into()),
..Default::default()
};
let _rebound = client
.workflows().evals()
.update(eval_id, UpdateParams::new(resource_body))
.await?;
Ok(())
}
<?php
require 'vendor/autoload.php';
use Retab\Client;
$client = new Client(apiKey: getenv('RETAB_API_KEY'));
$result = $client->workflows()->evals()->update(
evalId: 'eval_abc123',
);
print_r($result);
using Retab;
using RetabClient = Retab.Retab;
var apiKey = Environment.GetEnvironmentVariable("RETAB_API_KEY")!;
var client = new RetabClient(apiKey);
var result = await client.Workflows.Evals.UpdateAsync("eval_abc123", new WorkflowEvalsUpdateOptions());
Console.WriteLine(result);
import com.retab.RetabClient;
import com.retab.workflowevals.WorkflowEvalsApi;
public final class Example {
public static void main(String[] args) throws Exception {
RetabClient client = new RetabClient(System.getenv("RETAB_API_KEY"));
var result = new WorkflowEvalsApi(client).update("eval_abc123", "Invoice Processing", null, null);
System.out.println(result);
}
}
# Rename only
curl -X 'PATCH' \
'https://api.retab.com/v1/workflows/evals/wfnodeeval_hsLEQiM61ez9Piv147MWk' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <your-api-key>' \
-d '{ "name": "Q1 invoice — vendor name check" }'
# Replace the assertion
curl -X 'PATCH' \
'https://api.retab.com/v1/workflows/evals/wfnodeeval_hsLEQiM61ez9Piv147MWk' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <your-api-key>' \
-d '{
"assertion": {
"target": { "output_handle_id": "output-json-0", "path": "vendor.name" },
"condition": { "kind": "matches_regex", "pattern": "^Acme.*" }
}
}'
{
"id": "wfnodeeval_hsLEQiM61ez9Piv147MWk",
"workflow_id": "wf_abc123xyz",
"target": { "type": "block", "block_id": "block_extract_invoice" },
"source": { "type": "manual", "handle_inputs": { "...": "..." } },
"name": "Q1 invoice — vendor name check",
"assertion": { "...": "the new assertion" },
"schema_drift": "none",
"validation_status": "valid",
"latest_run_summary": null,
"created_at": "2026-04-08T14:22:26Z",
"updated_at": "2026-05-01T14:35:00Z"
}
{
"detail": "assertion cannot be null"
}
{
"detail": "Workflow eval not found: wfnodeeval_hsLEQiM61ez9Piv147MWk"
}
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Path Parameters
Body
Body for updating a workflow eval. Only the supplied fields (name, assertion, source) are changed.
Block-eval assertion against one declared output handle.
target is the only supported shape: an output handle id and an
optional relative path inside that handle's payload.
Show child attributes
Show child attributes
- ManualWorkflowEvalSource
- RunStepWorkflowEvalSource
Show child attributes
Show child attributes
Response
Successful Response
A saved workflow eval: a target block, an input source, and the assertion evaluated against its output.
Public workflow-eval target.
The storage layer remains block-scoped today, but the API shape names the tested entity explicitly so workflow-level targets can be added later.
Show child attributes
Show child attributes
- ManualWorkflowEvalSource
- RunStepWorkflowEvalSource
Show child attributes
Show child attributes
Block-eval assertion against one declared output handle.
target is the only supported shape: an output handle id and an
optional relative path inside that handle's payload.
Show child attributes
Show child attributes
Single-rule schema dependency for Level 2 drift detection.
Show child attributes
Show child attributes
valid, drifted, broken none, partial, drifted, unknown Show child attributes
Show child attributes
Show child attributes
Show child attributes
Summary of the most recent block-eval run.
Execution status and verdict outcome are exposed as separate fields.
The summary is written on terminal-state transitions, so in practice
status is one of completed | error | cancelled and outcome is
populated when status == "completed".
Show child attributes
Show child attributes
Summary of the most recent block-eval run.
Execution status and verdict outcome are exposed as separate fields.
The summary is written on terminal-state transitions, so in practice
status is one of completed | error | cancelled and outcome is
populated when status == "completed".
Show child attributes
Show child attributes
Summary of the most recent block-eval run.
Execution status and verdict outcome are exposed as separate fields.
The summary is written on terminal-state transitions, so in practice
status is one of completed | error | cancelled and outcome is
populated when status == "completed".
Show child attributes
Show child attributes
When the workflow eval was created
When the workflow eval was last updated