Skip to content

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