Skip to main content
Turn detection is the only thing that differs per framework. All six adapters share identical self-healing: the same evaluation, the same repair agent, the same validation. Each Harness.for_<framework>() factory wires the framework’s natural turn boundary to on_turn_end and preserves its session resolution (session identity comes from the PandaProbe SDK’s session context, so harness evaluations and SDK traces line up automatically). Adapters are optional, import-guarded extras:
Every factory accepts the same keywords: session_id= (a fixed session for single-conversation processes), config=, cli=, and replay= for closed-loop validation. To wire a ground-truth outcome oracle, use Harness.create(verifier=...) — the for_* factories do not take verifier=.

Turn granularity matters

Each adapter’s turn detector defines what a “turn” is, and that is what the trajectory gate sees. A detector that fires once per task — one Runner.run that internally takes 20 steps, one Crew.kickoff for a whole workflow — gives the gate a single sample per session, so gate_window is never reached and nothing can fire.If your framework’s natural boundary is coarse, either drive the loop in smaller units (one Runner.run per user turn) or call harness.on_turn_end(...) yourself at the granularity you want. The adapters wire the natural boundary; they cannot know whether it is the right one for your agent.

The barrier with an adapter

Adapters call on_turn_end for you, which is fire-and-forget. To get in-session healing, await the barrier after the framework’s turn returns:
harness.turn(session_id, settle=True) is the equivalent when you own the boundary; with an adapter, the explicit settle() after the framework call is the same thing. See the barrier.

LangGraph (LangChain & DeepAgents work the same way)

Like the SDK’s LangGraph tracing integration, the handler must be passed via config["callbacks"] on each invocation — the LangChain family has no instrument() pattern.

CrewAI

Claude Agent SDK

OpenAI Agents SDK

Rebuilding the preamble per turn

You no longer need to. The task preamble is a constant — one sentence naming four read-only tools — so a prompt fixed at construction time is identical to one rebuilt every turn. Frameworks that pin the system prompt lose nothing. What the agent reads is always current regardless, because harness_rules_read and harness_rules_list render from the live store at call time. Runnable end-to-end sketches for every framework live in the repository’s examples/misc/ directory.