Skip to main content
Plug opfor into your observability stack (Langfuse or Netra) and it unlocks two capabilities:
  • Grounded attack generation — opfor reads real production traces before generating attacks, so they mirror actual user flows, tool calls, and data instead of being generic.
  • Judge enrichment — opfor injects a trace ID into each target request, fetches the recorded trace afterward, and passes every tool call, retrieval, and span to the judge. This catches PII that leaks into a tool call but never reaches the user, and agents that fetch unauthorized data but render a clean reply.
Available for agent targets via the CLI today. Add the telemetry block below to your agent config file.
Ingestion delay: observability platforms process spans asynchronously. Opfor polls for the trace after all turns complete, so on multi-turn attacks some spans may not have arrived yet. Tune traceFetchInitialDelayMs, traceFetchMaxAttempts, and traceFetchRetryDelayMs at the cost of a longer scan. Grounded attack generation reads historic traces and isn’t affected.

Setup

"telemetry": {
  "provider": "langfuse",
  "langfuse": {
    "baseUrl": "https://cloud.langfuse.com",
    "traceSelection": { "lookbackHours": 24 }
  },
  "propagation": { "headers": { "X-Langfuse-Trace-Id": "{{traceId}}" } },
  "enrichJudgeFromTrace": true
}
export LANGFUSE_PUBLIC_KEY=pk-lf-...
export LANGFUSE_SECRET_KEY=sk-lf-...
Use langfuse.publicKeyEnv / langfuse.secretKeyEnv for custom env var names.

Config reference

Top-level

FieldDescription
telemetry.provider"langfuse", "netra", or "none" — required
telemetry.enrichJudgeFromTraceFetch the recorded trace after each attack and pass spans to the judge
telemetry.traceFetchInitialDelayMsInitial delay before first trace fetch (ingestion lag). Default 1000 ms
telemetry.traceFetchMaxAttemptsMax polling attempts per trace. Default 8
telemetry.traceFetchRetryDelayMsBackoff between polling attempts. Default 1500 ms
telemetry.enrichJudgeTraceJsonMaxCharsMax JSON chars of merged trace passed to the judge. Default 40000

Propagation

FieldDescription
telemetry.propagation.headersHTTP headers set on each target request. Values support {{traceId}}, {{runId}}
telemetry.propagation.traceIdBodyFieldTop-level JSON body field to inject the trace ID into (e.g. "trace_id")
telemetry.propagation.traceIdStrategy"per-attack" (default) or "per-run"
telemetry.propagation.traceIdPrefixPrefix for generated trace IDs
Header values support ${VAR} substitution (e.g. "Authorization": "Bearer ${TARGET_TOKEN}").
FieldDescription
telemetry.langfuse.baseUrlAPI base URL. Default https://cloud.langfuse.com
telemetry.langfuse.baseUrlEnvEnv var that overrides baseUrl at runtime
telemetry.langfuse.publicKeyEnvEnv var holding the public key. Default LANGFUSE_PUBLIC_KEY
telemetry.langfuse.secretKeyEnvEnv var holding the secret key. Default LANGFUSE_SECRET_KEY
telemetry.langfuse.traceCurationListJsonMaxCharsMax chars of list JSON sent to the curator LLM. Default 28000
telemetry.langfuse.traceSummarySourceJsonMaxCharsMax chars of hydrated JSON sent to the summarizer LLM. Default 100000
telemetry.langfuse.traceSummaryForAttackMaxCharsMax chars of trace summary passed into attack generation. Default 26000
telemetry.langfuse.traceDetailFieldsfields param for GET /api/public/traces/{id}. Default core,io,observations,scores,metrics
telemetry.langfuse.observationV2Fieldsfields for /v2/observations when full hydration is needed
telemetry.langfuse.observationV2MaxPagesMax cursor pages per trace for v2 observations. Default 15
traceSelection
FieldDescription
lookbackHoursFetch traces from the last N hours
fromTimestamp / toTimestampISO 8601 bounds
setupTraceIdsExplicit trace IDs to always include (skips curation)
userId / sessionIdFilter by Langfuse user / session
nameFilter by trace name (e.g. "POST /chat")
tagsFilter to traces including all listed tags
environmentFilter by environment string (or array)
version / releaseFilter by trace version / release
orderBySort order, e.g. "timestamp.desc"
filterAdvanced Langfuse filter conditions (JSON array); takes precedence over direct params
observationName / observationTypePre-filter by observation name + type (GENERATION/SPAN/EVENT)
listLimitMax rows per page. Default 100
listMaxPagesList pages to fetch before curation. Default 1
fieldsField groups in list responses (e.g. "core,io,scores")
FieldDescription
telemetry.netra.baseUrlAPI base URL (e.g. http://localhost:3000)
telemetry.netra.baseUrlEnvEnv var that overrides baseUrl at runtime
telemetry.netra.apiKeyEnvEnv var holding the API key. Default NETRA_API_KEY
telemetry.netra.traceCurationListJsonMaxCharsMax chars of list JSON sent to the curator LLM. Default 28000
telemetry.netra.traceSummarySourceJsonMaxCharsMax chars of hydrated JSON sent to the summarizer LLM. Default 100000
telemetry.netra.traceSummaryForAttackMaxCharsMax chars of trace summary passed into attack generation. Default 26000
traceSelection
FieldDescription
lookbackHoursFetch traces from the last N hours
fromTime / toTimeISO 8601 bounds
setupTraceIdsExplicit trace IDs to always include (skips curation)
sessionId / userIdFilter by session / user
environmentFilter by environment string
listLimitMax rows per page (1–100). Default 50
listMaxPagesList pages to fetch before curation. Default 1