https://api.moveworks.ai/export/v1) and replays it into AgentX:
No extra dependency is needed - the importer uses only the SDK’s core requirements.
Prerequisites
- Data API credentials, minted by a Moveworks superadmin (Moveworks Setup → Credentials).
API key and OAuth2 client-credentials are both offered there; the importer takes the key and
sends it as
Authorization: Bearer <key>(override the header/scheme if your deployment differs). - An AgentX project API key (self-host: Settings → API access).
CLI: scheduled sync
The SDK installs anagentx-moveworks command built for cron. It keeps an incremental cursor
(~/.agentx/moveworks_cursor.json by default), so each run picks up where the last one ended:
--dry-run prints the mapped payloads without ingesting, --agent-name attributes
every trace to one agent instead of per-domain, --timestamp-field overrides the record
timestamp field the OData $filter uses (default created_time), and --no-cursor ignores the
cursor file. On any ingest failure the cursor is not advanced, so a re-run retries the window.
Three flags control evaluation of the imported traffic:
- Pattern/built-in checks (PII, empty response, tool failure, active patterns) and trace-scoped
online evaluators run on every imported trace automatically, same as any live traffic -
no flag needed (
--monitoris kept for compatibility). --judge-sessionsjudges every imported session with each enabled session-scoped evaluator (Session Baseline Judge included) after the sync. Needed for backfills: the engine’s automatic session sweep only looks at the last 24 hours of activity, so older imported conversations would otherwise never get a session verdict. The requests carryifStale=true, so a session the sweep (or a previous run) already scored is skipped, never judged twice. Each judgment is a real LLM call - budget accordingly on large backfills.--evaluate-against <dataset_or_config_id>grades each new imported interaction’s recorded input/output against that grading config’s criteria - see Evaluating Moveworks agents below.
Python API
Evaluating Moveworks agents
Moveworks agents run inside the Moveworks cloud and can’t be invoked from outside (no inbound converse API; Script Actions have outbound network disabled). That constrains how each kind of evaluation applies - but both kinds work: Online evaluation - fully supported. Every synced interaction rides the normal ingest pipeline: trace-scoped online evaluators sample and score it, patterns raise signals, and--judge-sessions gets whole conversations judged (goal progression, consistency,
resolution). One caveat to hold honestly: the Data API has a ~24h freshness SLA, so this is
continuous retroactive scoring - yesterday’s production judged today - not
at-the-moment scoring. Signals, triage, calibration, and judge tuning all apply unchanged.
Offline evaluation - grade recorded behavior instead of re-running the agent. A classic
dataset run calls your agent per case; with no way to invoke a Moveworks agent, the offline
paths work from what the agent already did:
-
--evaluate-against <id>grades each imported interaction against a grading config during the sync (one judge call per new interaction - the engine’s span dedupe means re-syncing a window never re-bills). Each verdict is recorded as a real one-result evaluation run, so ratings and justifications show up under Evaluate → Runs, and the report prints the average: -
The same thing per trace from code:
client.tracer.evaluate_trace(trace_id, dataset_id). - Datasets from production: any synced trace or conversation converts to a golden dataset case (multi-turn included) - the regression suite for grading future synced traffic, or the benchmark for evaluating a candidate replacement.
-
Model portability: replay a synced interaction’s input against other models
(
client.monitor.run_model_portability(trace_id, [...])) for a cost/quality comparison. -
If your deployment exposes any inbound HTTP entry point, the
http_endpointadapter closes the loop with real dataset runs.
Behavior and limits
- Idempotent: every trace carries a deterministic
span_id(mw:<interaction_id>) and the engine skips spans it has already ingested, so re-syncing a window never duplicates. - Historical timestamps are honored: traces land in AgentX dated when the conversation happened, not when it was imported, so the Overview windows, cost chart buckets, and session timelines attribute correctly.
- Near-real-time, not live: the Data API follows a ~24-hour freshness SLA and retains 30 days - an hourly or daily sync is the honest cadence.
- No token counts: Moveworks does not export usage, so these traces contribute nothing to the LLM cost chart.
- No fabricated failures: plugin calls carry served/used flags, not success/failure - the importer records those flags verbatim and never marks a tool call failed, so Moveworks traffic cannot generate false tool-failure signals.
- Deployment-tolerant field mapping: Data API field names vary between deployments and API
versions; the importer reads each field from a list of known candidates and skips only records
with no parseable timestamp (counted in the report as
skipped_no_time).

