Skip to main content

Integration adapters

EvalGate connects to agent ecosystems through adapters that translate a source’s own records into one canonical event contract, evalgate.integration.v1. Adapters do not run your agents or replace their frameworks. They report what happened, what was scored, and what a source claims, and they keep those three things apart.
The Harness², GEPA, and DSPy adapters and the /api/integrations/events endpoint are an unreleased candidate. They are in the source tree and tested against fixtures, but they are not in the published evalgate-sdk 3.14.1, and none of them is qualified against a live third-party run yet.

Five stances, never one passed field

Every event declares exactly one stance: An observed event cannot assert an outcome, an evaluated event must carry a metric or an outcome, and authorized or promoted events must state the claim they ask EvalGate to approve. EvalGate never applies an external adapter’s authorization or promotion; it records a pending human approval.

Ingestion guarantees

POST /api/integrations/events accepts up to 100 events and requires an API key with traces:write.
  • Explicit approval for writes. A batch is validated and lowered but not persisted unless it sets "dryRun": false. The SDK adapters are plan-only by default as well.
  • Idempotency. Each event’s key is sha256(ecosystem, adapterId, eventType, nativeEventId). A replay returns replayed; the same key with different content returns conflict. The adapter version and occurredAt are not part of the conflict hash, so re-importing with an approximated time still replays.
  • Tenant isolation. The organization comes only from the API key. An event that carries organizationId is rejected.
  • Redaction and provenance. Events are stored through the agent-evidence ingest, which redacts payloads, evidence previews, and approval reasons server-side regardless of client claims, scans every other stored value for credentials, and keeps the source schema, adapter version, and parent event for each record.
  • Manifest enforcement. An event is accepted only from a registered adapter, for an event type that adapter declares, with the stance the manifest declares for it.
Each event returns one result: validated, created, replayed, conflict, or rejected with a reason. One invalid event does not fail the batch.

Adapter manifests and readiness

Every adapter has a manifest in the adapter registry (evalgate.integration-manifest.v1) that declares its ecosystem, version, transport, capabilities (observe, evaluate, enforce), authentication, supported events, source schema, canonical mapping, replay behavior, limitations, test fixtures, and readiness. Readiness is one of planned, fixture_qualified, live_qualified, or production_supported. The schema rejects live_qualified or production_supported without a recorded live qualification, and rejects enforce for any adapter that only sees an action after it ran (OTLP telemetry and file imports). No adapter claims enforce. AutoGen tracing covers AgentChat 0.4+ run() and run_stream() on agents and teams in source; the published evalgate-sdk 3.14.1 traces only the legacy initiate_chat API.

Harness²

The harness2-runs adapter imports a finished Harness² namespace directory. It reads task summaries, judged.json, base_judged.json, selection records, and adoption records, and never runs Harness² or reads harness trees, transcripts, or deliverables.
A judge failure is recorded as an error outcome, never as a zero score. Cloud project, location, and endpoint identifiers from config.json are replaced by SHA-256 digests. Adoption is Harness²’s own decision; EvalGate promotion requires --request-promotion and a human approval. With --apply, judged task results also go to /api/harness/outcomes as metadata-only harness outcomes (score and cost; Harness² does not record token counts outside its substrate logs). --send and --apply fail closed. --apply first validates every event and writes nothing if any would be rejected; if a write then reports a conflict, the command stops and uploads no harness outcomes. Either way it lists each failed event and exits non-zero. Re-running after a fix is safe because accepted events replay. The mapping is derived from Harness² source at commit 1cfe254.

GEPA and DSPy

EvalGateMetric combines EvalGate evaluators and assertion helpers into one score plus feedback text, and the adapters hand it to the optimizer:
  • recorder.send(...) returns ok and a failures list; with apply=True it validates every event first and writes nothing if any would be rejected.
  • gepa_evaluator returns (score, side_info), so EvalGate feedback reaches GEPA’s reflection step.
  • dspy_feedback_metric(metric) returns dspy.Prediction(score=..., feedback=...), which dspy.GEPA reads as score-with-feedback and dspy.Evaluate sums.
  • GEPACandidateRecorder records candidate evaluations, acceptances, rejections, merges, and the best candidate with parent lineage. Pass it to GEPAConfig(callbacks=[...]) or dspy.GEPA(gepa_kwargs={"callbacks": [...]}). Candidate text is hashed unless capture_content=True. recorder.request_promotion(idx) records a pending promotion claim.
Install the optional extras with pip install "evalgate-sdk[gepa]" or "evalgate-sdk[dspy]" once released.

OpenInference

OTLP spans that follow OpenInference semantic conventions keep these fields on ingest through /api/otel/v1/traces:
  • span kind, input.value / output.value, and flattened llm.input_messages.* / llm.output_messages.* when no value is set;
  • model, provider (llm.provider or llm.system), prompt, completion, and total tokens, llm.cost.total, and the JSON llm.invocation_parameters;
  • session.id. user.id, whether sent as a span or a resource attribute, is stored only as a SHA-256 digest.
Values hidden by the producer (OPENINFERENCE_HIDE_* settings write __REDACTED__) are recorded under evalgate.openinference.hidden and never stored as span content.