Getting started — review_sync_app
Install and run
From review_sync_app/:
uv sync
uv run python -m review_sync_service.main
This starts the FastAPI service on 127.0.0.1:8002 by default. Confirm it is
up:
curl -s http://127.0.0.1:8002/health
# {"status": "ok"}
For local secrets and state overrides, copy
review_sync_service/.env.review_sync_service.template to
review_sync_service/.env.review_sync_service.local and adjust values there.
review-sync-service runs as an Azure Container App. A VPN connection is
required to reach it from a developer machine — see
06-deployment.md for infrastructure details and
operational commands. The .internal.-prefixed variant of this hostname
does not resolve correctly from outside the VNet and should not be used.
Once connected, confirm the service is up (the first request after the service has been idle can take 10-15 seconds to cold-start):
curl -s "https://review-sync-service.bravecliff-5469885d.swedencentral.azurecontainerapps.io/health"
# {"status": "ok"}
Every caller has its own caller key, issued by the platform team and set as
REVIEW_SYNC_API_KEY in the pod's environment. The deployed service requires
a known key on every /v1/langfuse-profiles route, reads included. Bindings
and sync jobs identify a known caller and still accept a call without a key
during a warning phase, so send your key from the start. See
Authentication for details.
Environment variables
The service reads, in order, REVIEW_SYNC_ENV_FILE (if set),
review_sync_service/.env.review_sync_service, and
review_sync_service/.env.review_sync_service.local — all optional, and the
first value found for a given variable wins, so .local (or
REVIEW_SYNC_ENV_FILE) is where to put values that should not be committed,
such as CALLER_KEY_VAULT_URL.
| Variable | Default | Purpose |
|---|---|---|
REVIEW_SYNC_HOST |
127.0.0.1 |
Bind host |
REVIEW_SYNC_PORT |
8002 |
Bind port |
REVIEW_SYNC_RELOAD |
false |
Enable uvicorn auto-reload for local development |
CALLER_KEY_VAULT_URL |
(unset) | Key Vault whose review-sync-caller-<caller-id> secrets are the caller keys, for example https://semantic-eval-dev-kv.vault.azure.net/. Unset leaves every route open and identifies no caller, with a startup warning |
REVIEW_SYNC_QUEUE_PAGE_SIZE |
50 |
Default Langfuse queue fetch page size when a sync-job request does not set page_size |
REVIEW_SYNC_STATE_DIR |
review_sync_service/state/ |
Root directory for bindings, Langfuse profiles, jobs, checkpoints, and cleanup audits |
REVIEW_SYNC_BINDINGS_FILE |
{STATE_DIR}/v1/bindings.json |
Binding registry file path (overrides REVIEW_SYNC_STATE_DIR) |
REVIEW_SYNC_LANGFUSE_PROFILES_FILE |
{STATE_DIR}/langfuse_profiles.json |
Langfuse profile registry file path (overrides REVIEW_SYNC_STATE_DIR) |
REVIEW_SYNC_JOBS_DIR |
{STATE_DIR}/jobs |
Stored job-result directory (overrides REVIEW_SYNC_STATE_DIR) |
REVIEW_SYNC_CHECKPOINTS_DIR |
{STATE_DIR}/checkpoints |
Handled-version checkpoint directory (overrides REVIEW_SYNC_STATE_DIR) |
REVIEW_SYNC_CLEANUP_AUDITS_DIR |
{STATE_DIR}/cleanup_audits |
Cleanup audit record directory (overrides REVIEW_SYNC_STATE_DIR) |
REVIEW_SYNC_ARTIFACTS_DIR |
review_sync_service/outputs/ |
Persisted per-job debug artifacts |
Langfuse project credentials are never read from environment variables — they are registered per profile through the HTTP API. See 03-langfuse-profiles-and-cleanup.md.
Register a Langfuse connection profile
A sync job cannot read a queue until the binding's referenced profile is registered:
curl -s -X POST http://127.0.0.1:8002/v1/langfuse-profiles \
-H "Content-Type: application/json" \
-d '{
"profile_id": "reference-pod",
"base_url": "https://cloud.langfuse.com",
"public_key": "pk-lf-...",
"secret_key": "sk-lf-..."
}'
public_key and secret_key may be literal strings (as above, for local
development) or Azure Key Vault secret URIs; the service resolves the URI at
sync-job execution time via managed identity. A local service has no
CALLER_KEY_VAULT_URL, so this call needs no key there. See
03-langfuse-profiles-and-cleanup.md
for the full profile model.
Register a binding
A binding is data only — it names one queue, one target dataset, a review policy, and how to map reviewed fields into that dataset's schema. Validate it first, then store it:
curl -s -X POST http://127.0.0.1:8002/v1/bindings/validate \
-H "Content-Type: application/json" \
-d @binding.json
curl -s -X PUT http://127.0.0.1:8002/v1/bindings/reference-pod-routing \
-H "Content-Type: application/json" \
-d @binding.json
See 01-bindings.md for the full binding model and a
complete example binding.json, including the required langfuse_profile_id
field.
Trigger a sync job
curl -s -X POST http://127.0.0.1:8002/v1/sync-jobs \
-H "Content-Type: application/json" \
-d '{"binding_id": "reference-pod-routing", "dry_run": true}'
The response is a JobResult carrying a summary with per-outcome item
counts (published_items, skipped_unchanged_items, policy_skipped_items,
failed_publish_items, and how many records were deferred). Run with
"dry_run": false once the dry run looks right — see
02-sync-execution.md for the full execution flow and
what each outcome means.
In real usage, pods do not build these requests by hand — the SDK's
ReviewSyncServiceClient in sdk/semantic_evaluation and the pod-side CLIs in
reference_pod_implementations/{agent-framework-pod,langchain-pod}/evaluation/review_to_dataset/
do this over HTTP.
Resetting local state
uv run python scripts/reset_local_state.py
Deletes review_sync_service/state/ and review_sync_service/outputs/ so
the next run starts from a clean binding registry, profile registry,
checkpoint state, and artifact directory. Pass --keep-dirs to recreate the
empty directories immediately instead of waiting for the next write.
Where to go next
| File | What it covers |
|---|---|
| changelog.md | What a caller notices change, per deploy and API major |
| 00-review-sync-overview.md | Architecture, boundary, module map |
| 01-bindings.md | The binding model, review policy, and field projections |
| 02-sync-execution.md | Sync-job execution flow, checkpoints, and promotion outcomes |
| 03-langfuse-profiles-and-cleanup.md | The Langfuse connection profile model and queue cleanup |
| 04-api-reference.md | Every HTTP route |
| 05-testing.md | Test-suite layers |