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.
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 returnsreplayed; the same key with different content returnsconflict. The adapter version andoccurredAtare 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
organizationIdis 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.
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²
Theharness2-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(...)returnsokand afailureslist; withapply=Trueit validates every event first and writes nothing if any would be rejected.gepa_evaluatorreturns(score, side_info), so EvalGate feedback reaches GEPA’s reflection step.dspy_feedback_metric(metric)returnsdspy.Prediction(score=..., feedback=...), whichdspy.GEPAreads as score-with-feedback anddspy.Evaluatesums.GEPACandidateRecorderrecords candidate evaluations, acceptances, rejections, merges, and the best candidate with parent lineage. Pass it toGEPAConfig(callbacks=[...])ordspy.GEPA(gepa_kwargs={"callbacks": [...]}). Candidate text is hashed unlesscapture_content=True.recorder.request_promotion(idx)records a pending promotion claim.
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 flattenedllm.input_messages.*/llm.output_messages.*when no value is set; - model, provider (
llm.providerorllm.system), prompt, completion, and total tokens,llm.cost.total, and the JSONllm.invocation_parameters; session.id.user.id, whether sent as a span or a resource attribute, is stored only as a SHA-256 digest.
OPENINFERENCE_HIDE_* settings write
__REDACTED__) are recorded under evalgate.openinference.hidden and never
stored as span content.