Sep 21, 2026

Building an agent harness with Jev

Use Jev for focused judgments inside an agent harness, with explicit state, application-owned rules, fallback behavior, and evidence from each action.

AI ENGINEERING4 min readThe Currai team / Engineering

An agent can identify the right next step and still fail because the application gives it an expired link, an incomplete tool result, or permission to repeat an action that already succeeded. The harness owns those details: it supplies context, exposes tools, executes actions, and decides when to stop.

Jev can supply judgments at specific points in that harness. LangChain's Jev article shows examples of model selection and tool-risk checks. Here we'll use a different case: a workspace onboarding assistant that helps users invite teammates.

Start with the decision boundary

A user says, "The invite never arrived. Can you send it again?"

The assistant needs to understand what the user means. But the application already knows whether the user can invite members, which workspace is active, and whether an invitation was recently sent. Those facts should come from the backend.

A proposed workflow could divide responsibility this way:

StepResponsibility
Recognize an invitation troubleshooting requestJev judgment
Check workspace membership and invite permissionsBackend checks
Retrieve invitation statusRead-only tool
Decide whether the supplied explanation addresses the reported problemJev judgment
Resend an invitation when permitted and requestedBackend operation
Describe the result to the userTemplate or generative model

Writing down this boundary prevents a vague instruction such as "resolve the issue" from quietly taking ownership of the whole workflow.

Make the state inspectable

Use named fields for the latest request, the relevant conversation, and the invitation status. TypeSafe's state documentation supports structured JSON inputs, which lets questions refer to specific pieces of evidence.

An application-level snapshot might look like this:

{
  "request": "The invite never arrived. Can you send it again?",
  "invitation": {
    "status": "pending",
    "recipient_matches_request": true,
    "resend_allowed": false
  },
  "policy": {
    "blocked_resend_explanation": "A recent invitation is still being delivered."
  }
}

This is a suggested state structure, not an API response. Code computes the booleans from authoritative records. The model can interpret the request without being asked to calculate a resend window or infer permissions from conversational language.

Keep the full backend record available for debugging, but send only the fields needed for the judgment. It becomes much easier to explain a wrong route when the input is small enough to read.

Batch questions that use the same evidence

You might ask whether the user wants another invitation and whether the supplied explanation addresses their problem in one request. Both questions can use the snapshot above.

A question about the result of resending must wait until the operation finishes. Questions in one Jev request are independent; an answer to one does not supply new context to another. TypeSafe documents this distinction in its primitives guide.

That gives the harness a straightforward loop: capture state, request judgments, apply application rules, perform an allowed operation, then read fresh state. Put a limit on the number of attempts. An assistant that keeps reconsidering an unchanged invitation has stopped making progress.

Use LangChain at a specific lifecycle point

For Python applications, LangChain exposes TypeSafeClassifier as a runnable. Pass both state and questions to invoke; responses group answers under choices, scores, and nouls. The package also includes experimental model-routing and tool-risk middleware, which require the experimental installation extra. Consult the current LangChain TypeSafe integration before adopting those interfaces.

For this onboarding example, a custom routing step before the invitation handler is a reasonable starting point. You can test it without changing the execution semantics of the invitation tool.

The handler must still enforce permissions and resend limits. Treat the classifier's route as input to that handler. A confident request classification does not create authorization to change a workspace.

Preserve failures as well as successful actions

Record what the harness proposed, what the application allowed, and what the tool actually returned. These are different events. A successful classifier call followed by a failed resend should remain a failed resend in the record.

For rollout, compare the proposed handler with your existing behavior before enabling it. Review cases where the classifier disagrees, where the backend blocks an action, and where users repeat the request. Each group can reveal a different problem: an unclear category, a missing explanation, or an operation that never completed.

The Jev production evaluation guide expands this into a repeatable review process.

Review the agent's behavior with Currai

Instrument the harness with the Currai integration skill so captured events include the meaningful request, operation, and response. In Currai, use User Stories to review the conversation goal and outcome, then define a violation rule for responses that claim an invitation was sent without supporting tool evidence.

That makes the review concrete: open the matched conversation, inspect the evidence, and fix the step responsible. Get started with Currai.

03

Keep going with nearby topics from the Currai blog.