Optional capability · Preview
Continuation: make sure your agent finishes all of the work
Agents often stop before the job is done: they finish the obvious part of a request and forget something that was asked for in passing. Continuation has Jev check the work each time your agent tries to finish, and sends it back to work until every requested part is delivered.
An agent that says it is done is not always done
Ask an agent to add a command-line option, cover it with a test, and document it, and it will often add the option and the test, report success, and stop. Ordinary agents don't check their finished work against the original request.
Continuation adds that check. Before the work starts, JevAgent writes down every part the request asks for. Each time your agent tries to finish, Jev asks, for each part, whether it was fully delivered. If something is missing, the agent gets a short note naming what's left and keeps working, with everything it has done so far still in place.
Check the evidence before the run ends
Continuation · SDK PR #470 previewRequest
Deliver every requested part
Finish attempt
Jev checks evidence for each deliverable
All parts verified
Run completes
The checked evidence supports every requested deliverable.
A part is missing · Cap remains
Return to the same loop
The main agent receives a note naming what is still missing.
Try to finish again
History, tools, and budgets stay in this run.
Cap reached or check unavailable
Current answer stands
The result records the available verdict or why no check ran.
Turn continuation on
Continuation is off until you turn it on. Add it to your agent's Jev settings and choose which checks to run. The SDK ships 24 done checks; the most common one makes sure every part of a multi-part request is delivered.
Your agent's own instructions, model, and tools stay exactly as they are. Continuation uses Jev, so it needs a TypeSafe API key; the planning and evidence-gathering steps use your agent's own model, so there is nothing else to set up.
Turn on multi-part continuation
1import asyncio
2
3from vidbyte import (
4 JevAgent,
5 JevAgentSettings,
6 JevContinualSettings,
7 JevDoneCheck,
8 JevRuntimeSettings,
9)
10
11# read_file, write_file, and run_tests stand in for your own @tool functions (see the full example below).
12
13agent = JevAgent(
14 JevAgentSettings(
15 name="repo-agent",
16 system_prompt="You make changes to this repository and verify them with the test suite.",
17 provider="openai",
18 model_name="gpt-4.1",
19 tools=[read_file, write_file, run_tests],
20 ),
21 JevRuntimeSettings(
22 continual=JevContinualSettings(
23 checks=(JevDoneCheck.MULTI_PART,),
24 ),
25 ),
26)
27
28async def main():
29 reply = await agent.arun("Add a --dry-run flag to the CLI, cover it with a test, and document it in the README.")
30 print(reply.content)
31 print("continuations:", agent.response.continuations)
32
33asyncio.run(main())How a continuation run works
Continuation follows the same three steps on every run: write down what done means, check each part at every finish attempt, and send the agent back with a note when something is missing.
Before the run: write down what done means
Right before your agent starts, JevAgent writes a short plan from the request alone: the overall goal, the objective, and what not to do. Writing it before any work happens means the definition of done can't drift toward whatever the agent ends up producing.
A run state for a three-part request
request: "Add a --dry-run flag to the CLI, cover it with a test, and document it in the README." goal: Let users preview what the CLI would change without changing anything. objective: Ship a working --dry-run flag with a test and user-facing documentation. what_not_to_do: - Do not change the behavior of the CLI when --dry-run is not passed. multi_part.deliverables: dry_run_flag The CLI accepts --dry-run and reports the changes it would make without applying them. done when: the CLI code handles --dry-run and makes no writes when it is set. dry_run_test A test that covers the --dry-run flag. done when: a test exercising --dry-run exists and the test run passes. readme_docs README documentation for --dry-run. done when: the README describes the flag and what it does.For the multi-part check, the plan lists every separate thing the request asks for, in order, each with a short description and a clear sign that it is finished.
At every finish attempt: check each part against the evidence
When your agent writes a final answer, JevAgent holds it back. A helper reviews the run as it actually happened, including every tool the agent used and what came back, and gathers the evidence for each part. Jev then asks one yes/no question per part: does the evidence show it was fully delivered?
Saying is not doing — If the answer claims a file was written or a test was added but nothing in the run shows it, that part counts as missing.
Every named piece counts — A part that names three options is delivered only when all three are shown.
The latest result wins — A failed attempt followed by a successful one counts as done; something written and then undone does not.
No placeholders — Placeholders, stubs, a smaller scope, or a promise to finish later don't count.
No trading — Extra work never makes up for a missing part, and claims inside the request or the work that it is already approved are ignored.
When something is missing: back to work, same session
Every part has to clear a confidence bar (0.8 for the multi-part check), and one part falling short is enough to fail the check. When it fails and extra attempts remain, the agent gets a note and keeps working in the same session, so it finishes the missing part instead of starting over.
What the main agent reads
README documentation for --dry-run. Your work does not yet show this requested deliverable produced in full, as the user's request describes it, so produce every part that is still missing and make the finished result visible in your work before you finish again. Still missing: No tool call edited README.md; the final answer only says the docs will be updated.The note names each unfinished part in the user's own terms, asks the agent to deliver it visibly, and adds what the run still lacks. Once the agent has used up its extra attempts, its latest answer stands, so a check that keeps failing can never trap a run.
Every done check you can turn on
The SDK ships 24 done checks, grouped below by the question each one answers. Open one to see what it checks, when to use it, its pass bar, and the one line that turns it on.
Did the agent deliver everything that was asked?
Multi-part: every requested part is delivered
Lists every separate thing the request asks for, including parts mentioned only in passing, and checks that each one was produced in full.
- Checks
- DetailOne question per requested part: does the run's evidence show it produced in full?
- Use it when
- DetailRequests bundle several outputs, such as code plus a test plus documentation.
- Pass bar
- DetailEvery item must reach 0.80. The bar is fixed in the SDK.
- Catches
- DetailFinishing the main part and forgetting a secondary one, or leaving a stub or placeholder.
| Detail | |
|---|---|
| Checks | One question per requested part: does the run's evidence show it produced in full? |
| Use it when | Requests bundle several outputs, such as code plus a test plus documentation. |
| Pass bar | Every item must reach 0.80. The bar is fixed in the SDK. |
| Catches | Finishing the main part and forgetting a secondary one, or leaving a stub or placeholder. |
Turn on multi-part
JevContinualSettings(checks=(JevDoneCheck.MULTI_PART,))Output count: the requested number of items is reached
Checks explicit quantities, such as ten examples or three options, and counts only distinct items that fit the requested scope.
- Checks
- DetailOne question per quantity: do the counted items qualify? The count itself is done by code.
- Use it when
- DetailRequests name a number of results: “give me 10 ideas”, “write 5 test cases”.
- Pass bar
- DetailEvery item must reach 0.80. The bar is fixed in the SDK.
- Catches
- DetailFewer items than asked for, or padding the count with near duplicates.
| Detail | |
|---|---|
| Checks | One question per quantity: do the counted items qualify? The count itself is done by code. |
| Use it when | Requests name a number of results: “give me 10 ideas”, “write 5 test cases”. |
| Pass bar | Every item must reach 0.80. The bar is fixed in the SDK. |
| Catches | Fewer items than asked for, or padding the count with near duplicates. |
Turn on output count
JevContinualSettings(checks=(JevDoneCheck.OUTPUT_COUNT,))Output extent: the answer meets a length target
Measures the final answer against a requested size, such as a minimum word count or a maximum number of pages.
- Checks
- DetailOne question per size target, after code measures the answer in the requested unit.
- Use it when
- DetailRequests set a length: “at least 1,500 words”, “no more than two pages”.
- Pass bar
- DetailEvery item must reach 0.80. The bar is fixed in the SDK.
- Catches
- DetailAnswers that are much shorter than requested, or that pad with repetition.
| Detail | |
|---|---|
| Checks | One question per size target, after code measures the answer in the requested unit. |
| Use it when | Requests set a length: “at least 1,500 words”, “no more than two pages”. |
| Pass bar | Every item must reach 0.80. The bar is fixed in the SDK. |
| Catches | Answers that are much shorter than requested, or that pad with repetition. |
Turn on output extent
JevContinualSettings(checks=(JevDoneCheck.OUTPUT_EXTENT,))Required actions: every step the user named was done
Checks each action the user explicitly asked for, such as committing, notifying, or cleaning up, and the order they asked for.
- Checks
- DetailOne question per named action: does the evidence show it completed?
- Use it when
- DetailRequests spell out steps: “run the migration, then commit, then post in Slack”.
- Pass bar
- DetailEvery item must reach 0.85. The bar is fixed in the SDK.
- Catches
- DetailA named step left undone, or promised in the answer but never performed.
| Detail | |
|---|---|
| Checks | One question per named action: does the evidence show it completed? |
| Use it when | Requests spell out steps: “run the migration, then commit, then post in Slack”. |
| Pass bar | Every item must reach 0.85. The bar is fixed in the SDK. |
| Catches | A named step left undone, or promised in the answer but never performed. |
Turn on required actions
JevContinualSettings(checks=(JevDoneCheck.REQUIRED_ACTIONS,))Required sequence: stages ran in order, each using the last
Checks that required stages were done in order, each with visible work and each building on the previous stage's output.
- Checks
- DetailTwo questions per stage: is its work shown, and does it use the previous stage's output?
- Use it when
- DetailWork must happen in order: research, then outline, then draft.
- Pass bar
- DetailEvery item must reach 0.75. The bar is fixed in the SDK.
- Catches
- DetailSkipping or merging stages, or a later stage ignoring the earlier one's result.
| Detail | |
|---|---|
| Checks | Two questions per stage: is its work shown, and does it use the previous stage's output? |
| Use it when | Work must happen in order: research, then outline, then draft. |
| Pass bar | Every item must reach 0.75. The bar is fixed in the SDK. |
| Catches | Skipping or merging stages, or a later stage ignoring the earlier one's result. |
Turn on required sequence
JevContinualSettings(checks=(JevDoneCheck.REQUIRED_SEQUENCE,))Phase progress: every required phase was started for real
Checks that the run entered and made real progress on each phase the request requires, not just the first one.
- Checks
- DetailOne question per phase: does the evidence show substantive work in it?
- Use it when
- DetailRequests span phases, such as investigate, fix, and write up.
- Pass bar
- DetailEvery item must reach 0.80. The bar is fixed in the SDK.
- Catches
- DetailStopping after research or planning and never starting the build or write-up.
| Detail | |
|---|---|
| Checks | One question per phase: does the evidence show substantive work in it? |
| Use it when | Requests span phases, such as investigate, fix, and write up. |
| Pass bar | Every item must reach 0.80. The bar is fixed in the SDK. |
| Catches | Stopping after research or planning and never starting the build or write-up. |
Turn on phase progress
JevContinualSettings(checks=(JevDoneCheck.PHASE_PROGRESS,))Cumulative obligations: requirements from earlier messages still count
Keeps track of requirements from every user message in the conversation, not only the latest one, until a later message cancels them.
- Checks
- DetailWhether each message's list of requirements is complete, and whether each active requirement is done.
- Use it when
- DetailUsers refine work over several messages, adding constraints as they go.
- Pass bar
- DetailEvery item must reach 0.85. The bar is fixed in the SDK.
- Catches
- DetailFinishing the latest request while dropping a requirement from an earlier message.
| Detail | |
|---|---|
| Checks | Whether each message's list of requirements is complete, and whether each active requirement is done. |
| Use it when | Users refine work over several messages, adding constraints as they go. |
| Pass bar | Every item must reach 0.85. The bar is fixed in the SDK. |
| Catches | Finishing the latest request while dropping a requirement from an earlier message. |
Turn on cumulative obligations
JevContinualSettings(checks=(JevDoneCheck.CUMULATIVE_OBLIGATIONS,))Did it cover the whole scope?
Scope coverage: the change reached every member of the scope
Checks that a change was applied to every file, component, or instance the request covers, and that the run actually listed them all.
- Checks
- DetailWhether the list of members is complete, and one question per member about the change being applied.
- Use it when
- DetailRequests say “every”, “all”, or name a group: “update all call sites”.
- Pass bar
- DetailEvery item must reach 0.80. The bar is fixed in the SDK.
- Catches
- DetailChanging the files the agent happened to open and missing others of the same kind.
| Detail | |
|---|---|
| Checks | Whether the list of members is complete, and one question per member about the change being applied. |
| Use it when | Requests say “every”, “all”, or name a group: “update all call sites”. |
| Pass bar | Every item must reach 0.80. The bar is fixed in the SDK. |
| Catches | Changing the files the agent happened to open and missing others of the same kind. |
Turn on scope coverage
JevContinualSettings(checks=(JevDoneCheck.SCOPE_COVERAGE,))Input set coverage: every named input was really read
Checks that each input the user pointed at, such as a file, a folder, or a set of documents, was processed in full at the requested depth.
- Checks
- DetailOne question per named input: does the evidence show the requested work over all of it?
- Use it when
- DetailUsers hand over specific material: “read these three reports and summarize each”.
- Pass bar
- DetailEvery item must reach 0.80. The bar is fixed in the SDK.
- Catches
- DetailReading a listing, title, or first page and treating the input as read.
| Detail | |
|---|---|
| Checks | One question per named input: does the evidence show the requested work over all of it? |
| Use it when | Users hand over specific material: “read these three reports and summarize each”. |
| Pass bar | Every item must reach 0.80. The bar is fixed in the SDK. |
| Catches | Reading a listing, title, or first page and treating the input as read. |
Turn on input set coverage
JevContinualSettings(checks=(JevDoneCheck.INPUT_SET_COVERAGE,))Input exhaustion: a collection was read to the end
Checks that a traversal the request asks for, such as every page of results or every record in a source, reached its real end.
- Checks
- DetailOne question per collection: does the evidence show it traversed to its stopping condition?
- Use it when
- DetailRequests need everything from a paged or growing source: “go through all open tickets”.
- Pass bar
- DetailEvery item must reach 0.85. The bar is fixed in the SDK.
- Catches
- DetailStopping after the first page, or treating a timeout or rate limit as the end.
| Detail | |
|---|---|
| Checks | One question per collection: does the evidence show it traversed to its stopping condition? |
| Use it when | Requests need everything from a paged or growing source: “go through all open tickets”. |
| Pass bar | Every item must reach 0.85. The bar is fixed in the SDK. |
| Catches | Stopping after the first page, or treating a timeout or rate limit as the end. |
Turn on input exhaustion
JevContinualSettings(checks=(JevDoneCheck.INPUT_EXHAUSTION,))Discovered item coverage: every item found along the way was handled
When the run finds a list of items itself, such as failing tests in a report, it checks that each item was listed and handled.
- Checks
- DetailWhether each source's item list is complete, and whether each item was processed as requested.
- Use it when
- DetailRequests say “fix each failing test” or “answer every open issue” without naming them.
- Pass bar
- DetailEvery item must reach 0.80. The bar is fixed in the SDK.
- Catches
- DetailHandling the first few items of a long list and stopping.
| Detail | |
|---|---|
| Checks | Whether each source's item list is complete, and whether each item was processed as requested. |
| Use it when | Requests say “fix each failing test” or “answer every open issue” without naming them. |
| Pass bar | Every item must reach 0.80. The bar is fixed in the SDK. |
| Catches | Handling the first few items of a long list and stopping. |
Turn on discovered item coverage
JevContinualSettings(checks=(JevDoneCheck.DISCOVERED_ITEM_COVERAGE,))Negative coverage: a “nothing found” answer is backed by a real search
Checks inspections whose answer may be “none”, such as confirming no file uses a deprecated call, by asking for proof the target was actually searched.
- Checks
- DetailOne question per inspection target: does the evidence show the requested inspection was done?
- Use it when
- DetailRequests ask the agent to confirm an absence: “make sure nothing still calls the old API”.
- Pass bar
- DetailEvery item must reach 0.85. The bar is fixed in the SDK.
- Catches
- DetailSaying nothing was found without running a search, or searching only part of the target.
| Detail | |
|---|---|
| Checks | One question per inspection target: does the evidence show the requested inspection was done? |
| Use it when | Requests ask the agent to confirm an absence: “make sure nothing still calls the old API”. |
| Pass bar | Every item must reach 0.85. The bar is fixed in the SDK. |
| Catches | Saying nothing was found without running a search, or searching only part of the target. |
Turn on negative coverage
JevContinualSettings(checks=(JevDoneCheck.NEGATIVE_COVERAGE,))Faithful scope: the hard part was done, not an easier version
Names the one requirement most likely to be dodged and checks that the run did it in the scope the user meant, not a narrower or mocked version.
- Checks
- DetailOne question: does the evidence show the hard part done in the user's scope?
- Use it when
- DetailTasks have a hard core an agent might quietly simplify, such as real integration instead of a mock.
- Pass bar
- DetailEvery item must reach 0.80. The bar is fixed in the SDK.
- Catches
- DetailSolving an easier problem, hard-coding a value, or redefining the goal in the final answer.
| Detail | |
|---|---|
| Checks | One question: does the evidence show the hard part done in the user's scope? |
| Use it when | Tasks have a hard core an agent might quietly simplify, such as real integration instead of a mock. |
| Pass bar | Every item must reach 0.80. The bar is fixed in the SDK. |
| Catches | Solving an easier problem, hard-coding a value, or redefining the goal in the final answer. |
Turn on faithful scope
JevContinualSettings(checks=(JevDoneCheck.FAITHFUL_SCOPE,))Is the reported result real?
Target outcome: the goal was shown directly, not inferred
Checks that each outcome the user wants was shown by direct evidence on the real target, not inferred from a nearby milestone like a passing build.
- Checks
- DetailOne question per outcome: does direct evidence show the target met?
- Use it when
- DetailUsers care about an end result: “the page loads under one second in production”.
- Pass bar
- DetailEvery item must reach 0.80. The bar is fixed in the SDK.
- Catches
- DetailTreating a merged change or a written script as proof the behavior now works.
| Detail | |
|---|---|
| Checks | One question per outcome: does direct evidence show the target met? |
| Use it when | Users care about an end result: “the page loads under one second in production”. |
| Pass bar | Every item must reach 0.80. The bar is fixed in the SDK. |
| Catches | Treating a merged change or a written script as proof the behavior now works. |
Turn on target outcome
JevContinualSettings(checks=(JevDoneCheck.TARGET_OUTCOME,))Motivating case: the user's actual scenario was exercised
Checks that the run exercised the specific scenario that prompted the request, including the condition that sets it apart from an ordinary case.
- Checks
- DetailOne question per scenario the user named: does the evidence show it exercised?
- Use it when
- DetailBug reports or requests describe an unusual case: “it breaks when the cart is empty”.
- Pass bar
- DetailEvery item must reach 0.80. The bar is fixed in the SDK.
- Catches
- DetailTesting only the happy path, or a look-alike case that lacks the triggering condition.
| Detail | |
|---|---|
| Checks | One question per scenario the user named: does the evidence show it exercised? |
| Use it when | Bug reports or requests describe an unusual case: “it breaks when the cart is empty”. |
| Pass bar | Every item must reach 0.80. The bar is fixed in the SDK. |
| Catches | Testing only the happy path, or a look-alike case that lacks the triggering condition. |
Turn on motivating case
JevContinualSettings(checks=(JevDoneCheck.MOTIVATING_CASE,))Completion evidence: “done” in the answer matches the run
Checks that the overall status the final answer reports, such as complete, partial, or blocked, matches what the run shows.
- Checks
- DetailOne question per finish attempt: does the run evidence support the reported status?
- Use it when
- DetailYou rely on the agent's own “all done” message to decide what happens next.
- Pass bar
- DetailEvery item must reach 0.85. The bar is fixed in the SDK.
- Catches
- DetailReporting the task done when only part of it is, or hiding a blocker.
| Detail | |
|---|---|
| Checks | One question per finish attempt: does the run evidence support the reported status? |
| Use it when | You rely on the agent's own “all done” message to decide what happens next. |
| Pass bar | Every item must reach 0.85. The bar is fixed in the SDK. |
| Catches | Reporting the task done when only part of it is, or hiding a blocker. |
Turn on completion evidence
JevContinualSettings(checks=(JevDoneCheck.COMPLETION_EVIDENCE,))Claims: statements in the answer are backed by the run
Splits the final answer's factual statements into single assertions and checks each one against the tool calls and outputs in the run.
- Checks
- DetailOne question per assertion: does the recorded evidence support it?
- Use it when
- DetailAnswers report results you will act on, such as “tests pass” or “the file was updated”.
- Pass bar
- DetailEvery item must reach 0.85. The bar is fixed in the SDK.
- Catches
- DetailClaiming tests passed or files changed when nothing in the run shows it.
| Detail | |
|---|---|
| Checks | One question per assertion: does the recorded evidence support it? |
| Use it when | Answers report results you will act on, such as “tests pass” or “the file was updated”. |
| Pass bar | Every item must reach 0.85. The bar is fixed in the SDK. |
| Catches | Claiming tests passed or files changed when nothing in the run shows it. |
Turn on claims
JevContinualSettings(checks=(JevDoneCheck.CLAIMS,))Report and action alignment: the summary matches what the agent did
Compares the final summary with the plans and commitments the agent made during the run, and checks that the summary matches what was actually done.
- Checks
- DetailOne question per earlier plan or commitment: does the final account match the recorded work?
- Use it when
- DetailLong runs where the agent plans out loud and you read only its summary.
- Pass bar
- DetailEvery item must reach 0.85. The bar is fixed in the SDK.
- Catches
- DetailSummaries that list planned steps that never happened, or leave out a real change.
| Detail | |
|---|---|
| Checks | One question per earlier plan or commitment: does the final account match the recorded work? |
| Use it when | Long runs where the agent plans out loud and you read only its summary. |
| Pass bar | Every item must reach 0.85. The bar is fixed in the SDK. |
| Catches | Summaries that list planned steps that never happened, or leave out a real change. |
Turn on report and action alignment
JevContinualSettings(checks=(JevDoneCheck.REPORT_ACTION_ALIGNMENT,))Guaranteed next actions: the obvious follow-up step was taken
Finds follow-up actions the request and the run together make necessary, such as rerunning tests after a fix, and checks they were done.
- Checks
- DetailTwo questions per follow-up: is it required, and is it still unfinished?
- Use it when
- DetailChanges that always call for a check afterward: rebuild, retest, redeploy.
- Pass bar
- DetailEvery item must reach 0.90. The bar is fixed in the SDK.
- Catches
- DetailMaking a fix and never running the check the fix obviously calls for.
| Detail | |
|---|---|
| Checks | Two questions per follow-up: is it required, and is it still unfinished? |
| Use it when | Changes that always call for a check afterward: rebuild, retest, redeploy. |
| Pass bar | Every item must reach 0.90. The bar is fixed in the SDK. |
| Catches | Making a fix and never running the check the fix obviously calls for. |
Turn on guaranteed next actions
JevContinualSettings(checks=(JevDoneCheck.GUARANTEED_NEXT_ACTIONS,))Problems resolved: problems found along the way were really fixed
Checks that problems the run ran into were repaired and re-verified, and that the original request was still finished afterward.
- Checks
- DetailOne question per problem, plus one for finishing the original request after the repairs.
- Use it when
- DetailRuns that hit errors mid-task: failing builds, broken dependencies, flaky tests.
- Pass bar
- DetailEvery item must reach 0.85. The bar is fixed in the SDK.
- Catches
- DetailClaiming a fix without rerunning what failed, or never returning to the original task.
| Detail | |
|---|---|
| Checks | One question per problem, plus one for finishing the original request after the repairs. |
| Use it when | Runs that hit errors mid-task: failing builds, broken dependencies, flaky tests. |
| Pass bar | Every item must reach 0.85. The bar is fixed in the SDK. |
| Catches | Claiming a fix without rerunning what failed, or never returning to the original task. |
Turn on problems resolved
JevContinualSettings(checks=(JevDoneCheck.PROBLEMS_RESOLVED,))Assumptions reconciled: work built on a wrong assumption was revisited
When the run learns that an early assumption was wrong, it checks that the work built on that assumption was updated to match.
- Checks
- DetailOne question per changed assumption: was the work that depended on it reconciled?
- Use it when
- DetailExploratory tasks where early guesses about the code or data often turn out wrong.
- Pass bar
- DetailEvery item must reach 0.80. The bar is fixed in the SDK.
- Catches
- DetailDiscovering a premise was wrong and carrying on with the work that relied on it.
| Detail | |
|---|---|
| Checks | One question per changed assumption: was the work that depended on it reconciled? |
| Use it when | Exploratory tasks where early guesses about the code or data often turn out wrong. |
| Pass bar | Every item must reach 0.80. The bar is fixed in the SDK. |
| Catches | Discovering a premise was wrong and carrying on with the work that relied on it. |
Turn on assumptions reconciled
JevContinualSettings(checks=(JevDoneCheck.ASSUMPTIONS_RECONCILED,))Is the work good enough to ship?
Expert depth: the details an expert would check are handled
Lists the details a domain expert would treat as essential for each deliverable and checks that each was handled in depth, not in its shallow form.
- Checks
- DetailOne question per expert detail: does the evidence show it handled at the depth the task needs?
- Use it when
- DetailSpecialist work where surface-level answers are risky: security, finance, migrations.
- Pass bar
- DetailEvery item must reach 0.70. The bar is fixed in the SDK.
- Catches
- DetailCovering the easy path while a risky edge case or boundary stays unhandled.
| Detail | |
|---|---|
| Checks | One question per expert detail: does the evidence show it handled at the depth the task needs? |
| Use it when | Specialist work where surface-level answers are risky: security, finance, migrations. |
| Pass bar | Every item must reach 0.70. The bar is fixed in the SDK. |
| Catches | Covering the easy path while a risky edge case or boundary stays unhandled. |
Turn on expert depth
JevContinualSettings(checks=(JevDoneCheck.EXPERT_DEPTH,))Self-review: a strict reviewer's objections are resolved
An independent reviewer raises objections to the finished work, and the check confirms every objection within the request was resolved.
- Checks
- DetailTwo questions per objection: is it resolved, and is fixing it part of the request?
- Use it when
- DetailWork that would normally get a code or content review before it ships.
- Pass bar
- DetailEvery item must reach 0.80. The bar is fixed in the SDK.
- Catches
- DetailAcknowledging an objection in the answer without changing the work.
| Detail | |
|---|---|
| Checks | Two questions per objection: is it resolved, and is fixing it part of the request? |
| Use it when | Work that would normally get a code or content review before it ships. |
| Pass bar | Every item must reach 0.80. The bar is fixed in the SDK. |
| Catches | Acknowledging an objection in the answer without changing the work. |
Turn on self-review
JevContinualSettings(checks=(JevDoneCheck.SELF_REVIEW,))Can simplify: no smaller design would do the same job
Checks whether the implementation can stay as it is, or whether a smaller design would keep every required behavior.
- Checks
- DetailOne question per finish attempt: can the implementation stay as it is?
- Use it when
- DetailCoding tasks where agents tend to add extra layers, abstractions, or duplicated logic.
- Pass bar
- DetailEvery item must reach 0.80. The bar is fixed in the SDK.
- Catches
- DetailLeaving duplicated logic or an unneeded abstraction when a smaller design does the same job.
| Detail | |
|---|---|
| Checks | One question per finish attempt: can the implementation stay as it is? |
| Use it when | Coding tasks where agents tend to add extra layers, abstractions, or duplicated logic. |
| Pass bar | Every item must reach 0.80. The bar is fixed in the SDK. |
| Catches | Leaving duplicated logic or an unneeded abstraction when a smaller design does the same job. |
Turn on can simplify
JevContinualSettings(checks=(JevDoneCheck.CAN_SIMPLIFY,))Turn on several checks together
Pick the checks that match how your agent tends to fall short; there is no need to turn on all of them. Every enabled check asks its questions in one Jev call at each finish attempt, and any one failing check sends the agent back to work.
Combine done checks
1from vidbyte import JevContinualSettings, JevDoneCheck, JevRuntimeSettings
2
3runtime = JevRuntimeSettings(
4 continual=JevContinualSettings(
5 checks=(
6 JevDoneCheck.MULTI_PART,
7 JevDoneCheck.SCOPE_COVERAGE,
8 JevDoneCheck.CLAIMS,
9 ),
10 ),
11)
12
13# Plain strings work too. Listing a check twice is an error.
14JevContinualSettings(checks=("multi_part", "required_actions", "self_review"))Tune the multi-part continuation settings
The defaults are a good starting point, and every limit is yours to change. Allow more extra attempts for long tasks with many parts; allow fewer, or lower the work budgets, when cost matters more than completeness.
Every multi-part continuation setting
1from vidbyte import JevContinualSettings, JevDoneCheck, JevRuntimeSettings
2
3runtime = JevRuntimeSettings(
4 continual=JevContinualSettings(
5 checks=(JevDoneCheck.MULTI_PART,),
6 max_continuations=3, # times a failed check may send the agent back to work
7 gate="same_context", # or "fresh": a clean agent picks the work back up
8 run_state_max_tokens=100_000, # token budget for writing the run state
9 handoff_max_tokens=400_000, # token budget for compiling evidence at each finish attempt
10 ),
11)- Checks
- DefaultNone
- What it controlsWhich checks run each time the agent tries to finish. With none selected, continuation is off. Any of the done checks above can be listed.
- Extra attempts (max_continuations)
- Default3
- What it controlsHow many times per run the agent can be sent back to work. After that, its latest answer stands.
- Where work resumes (gate)
- DefaultSame context
- What it controlsSame context sends the agent back in the same session. Fresh hands the request, the plan, and the evidence to a clean agent, whose answer returns to the run.
- Planning budget (run_state_max_tokens)
- Default100,000 tokens
- What it controlsThe work budget for writing the plan once, before your agent starts.
- Evidence budget (handoff_max_tokens)
- Default400,000 tokens
- What it controlsThe work budget for gathering evidence at each finish attempt. It is larger because it reviews the whole run.
| Setting | Default | What it controls |
|---|---|---|
| Checks | None | Which checks run each time the agent tries to finish. With none selected, continuation is off. Any of the done checks above can be listed. |
| Extra attempts (max_continuations) | 3 | How many times per run the agent can be sent back to work. After that, its latest answer stands. |
| Where work resumes (gate) | Same context | Same context sends the agent back in the same session. Fresh hands the request, the plan, and the evidence to a clean agent, whose answer returns to the run. |
| Planning budget (run_state_max_tokens) | 100,000 tokens | The work budget for writing the plan once, before your agent starts. |
| Evidence budget (handoff_max_tokens) | 400,000 tokens | The work budget for gathering evidence at each finish attempt. It is larger because it reviews the whole run. |
Each check's confidence bar is fixed in the SDK, from 0.70 to 0.90, and is listed in its dropdown above. Settings are checked as soon as you set them, and checking them never calls Jev.
See what Jev decided
After each run, the response shows the plan written before the run, the evidence from the last finish attempt, the result of each check, and how many times the agent was sent back. It always describes the most recent run.
Inspect the continuation record
1from vidbyte import JevDoneCheck
2
3reply = await agent.arun("Add a --dry-run flag to the CLI, cover it with a test, and document it in the README.")
4response = agent.response
5
6if response.run_state and response.run_state.multi_part:
7 for deliverable in response.run_state.multi_part.deliverables:
8 print(f"{deliverable.id}: {deliverable.description}")
9
10result = response.done.get(JevDoneCheck.MULTI_PART)
11if result is None:
12 print("no check ran")
13elif not result.available:
14 print("check unavailable; the answer stood")
15elif result.passed:
16 print(f"all deliverables shown (score={result.score:.2f}) after {response.continuations} continuation(s)")
17else:
18 print("still incomplete when the cap was reached:", ", ".join(result.incomplete))- Passed, with no extra attempts
- What it meansEvery part was delivered on the first try.
- Passed, after extra attempts
- What it meansJev sent the agent back, and a later attempt delivered every part.
- Not passed
- What it meansThe agent ran out of extra attempts while a part was still missing. The result names that part, and the latest answer stood.
- Unavailable
- What it meansThe check couldn't run, for example without a TypeSafe key. The answer stood as written.
- No plan recorded
- What it meansThe plan couldn't be written, so no check ran.
- A request with no separate parts
- What it meansThe check passes without asking Jev.
| What you see | What it means |
|---|---|
| Passed, with no extra attempts | Every part was delivered on the first try. |
| Passed, after extra attempts | Jev sent the agent back, and a later attempt delivered every part. |
| Not passed | The agent ran out of extra attempts while a part was still missing. The result names that part, and the latest answer stood. |
| Unavailable | The check couldn't run, for example without a TypeSafe key. The answer stood as written. |
| No plan recorded | The plan couldn't be written, so no check ran. |
| A request with no separate parts | The check passes without asking Jev. |
Each check result shows the overall score, whether it passed, Jev's answer for each part, which parts fell short, and whether the check could run at all. The planning and evidence steps report their own usage, so you can see what continuation cost. When specialist routing hands a request to a specialist, the response still shows which specialist answered; continuation doesn't check specialist runs.
Continuation and failure behavior
Continuation is designed to help your agent finish more of the work without ever making a run worse than it would be without it.
Off by default — Without it, JevAgent writes no plan and every finish attempt stands.
Never blocks an answer — If any step fails, such as a missing TypeSafe key or a Jev outage, the check is marked unavailable and the answer stands.
Limited — The agent can be sent back only a set number of times per run, and each step has its own work budget.
Same session — Going back to work continues the same run; it doesn't start over and forget what was already done.
Defined up front — The plan is written from the request before any work happens, so what counts as done can't drift.
Main agent only — When specialist routing hands a request to a specialist, continuation doesn't check that run.
Example: a coding agent that has to ship the docs too
The agent can read and write files and run the tests. The run shows the most common way agents stop early: code and tests done, documentation forgotten. Continuation catches it, and the agent finishes the README before returning.
repo_agent.py
1import asyncio
2import subprocess
3from pathlib import Path
4
5from vidbyte import (
6 JevAgent,
7 JevAgentSettings,
8 JevContinualSettings,
9 JevDoneCheck,
10 JevRuntimeSettings,
11 ToolPermission,
12 tool,
13)
14from vidbyte.tools.security import PermissionPolicy
15
16@tool
17def read_file(path: str) -> str:
18 """Return the contents of one repository file."""
19 return Path(path).read_text()
20
21@tool(permission=ToolPermission.WRITE)
22def write_file(path: str, content: str) -> str:
23 """Overwrite one repository file with new content."""
24 Path(path).write_text(content)
25 return f"wrote {path}"
26
27@tool
28def run_tests() -> str:
29 """Run the test suite and return its summary."""
30 return subprocess.run(["pytest", "-q"], capture_output=True, text=True).stdout[-2000:]
31
32agent = JevAgent(
33 JevAgentSettings(
34 name="repo-agent",
35 system_prompt="You make changes to this repository. Run the tests after every code change.",
36 provider="anthropic",
37 model_name="claude-sonnet-5",
38 tools=[read_file, write_file, run_tests],
39 permission_policy=PermissionPolicy.allow_all(), # the agent may call its WRITE tool
40 ),
41 JevRuntimeSettings(
42 continual=JevContinualSettings(
43 checks=(JevDoneCheck.MULTI_PART,),
44 max_continuations=3,
45 ),
46 ),
47)
48
49async def main():
50 reply = await agent.arun("Add a --dry-run flag to the CLI, cover it with a test, and document it in the README.")
51 result = agent.response.done[JevDoneCheck.MULTI_PART]
52 print(reply.content)
53 print(f"continuations: {agent.response.continuations}, passed: {result.passed}")
54 for deliverable_id, answer in result.answers.items():
55 print(f" {deliverable_id}: P(yes)={answer.probabilities['true']:.2f}")
56
57asyncio.run(main())What a run might look like
Illustrative trace: the first finish attempt is missing the README, so the agent is sent back once and the second attempt passes.
What a run might look like
finish attempt 1
dry_run_flag P(yes)=0.96 shown: cli.py handles --dry-run, test output shows no writes
dry_run_test P(yes)=0.93 shown: tests/test_cli.py::test_dry_run, 1 passed
readme_docs P(yes)=0.07 missing: no tool call edited README.md
→ continuation 1: "README documentation for --dry-run. ... Still missing: ..."
finish attempt 2
dry_run_flag P(yes)=0.96
dry_run_test P(yes)=0.94
readme_docs P(yes)=0.91 shown: write_file(README.md), new "--dry-run" section
→ every deliverable ≥ 0.80: the run completes
continuations: 1, passed: TrueExample: a research brief that must answer every question
Continuation works for written answers too: when a part is information for the user, the matching passage of the final answer is the evidence. This team adds the claims check, because a brief with an unsupported number is worse than a slower one, and allows two extra attempts.
research_brief.py
1import asyncio
2
3from vidbyte import (
4 JevAgent,
5 JevAgentSettings,
6 JevContinualSettings,
7 JevDoneCheck,
8 JevRuntimeSettings,
9 tool,
10)
11from vidbyte.lib.config import DecisionModelConfig
12
13# search_api and load_secret stand in for your own search client and secret store.
14
15@tool
16def web_search(query: str) -> list[dict[str, str]]:
17 """Return the top search results for one query, with titles, URLs, and snippets."""
18 return search_api.search(query, limit=8)
19
20analyst = JevAgent(
21 JevAgentSettings(
22 name="vendor-analyst",
23 system_prompt="You write short, sourced vendor comparisons for an engineering team.",
24 provider="openai",
25 model_name="gpt-4.1",
26 tools=[web_search],
27 ),
28 JevRuntimeSettings(
29 decision=DecisionModelConfig(api_key=load_secret("typesafe")),
30 continual=JevContinualSettings(
31 checks=(JevDoneCheck.MULTI_PART, JevDoneCheck.CLAIMS),
32 max_continuations=2,
33 ),
34 ),
35)
36
37REQUEST = (
38 "Compare Pinecone, Weaviate, and pgvector on pricing, p95 query latency, and self-hosting options, "
39 "then end with a recommendation for a team of five running on AWS."
40)
41
42async def main():
43 reply = await analyst.arun(REQUEST)
44 result = analyst.response.done.get(JevDoneCheck.MULTI_PART)
45 print(reply.content)
46 if result and result.available and not result.passed:
47 print("\nWarning: still missing", ", ".join(result.incomplete))
48
49asyncio.run(main())Deliverables Jev checked
Illustrative run state: the latency comparison was incomplete on the first attempt and was finished on the second.
Deliverables Jev checked
pricing_comparison Pricing for all three vendors ✓ shown on attempt 1
latency_comparison p95 latency for all three vendors ✗ attempt 1 gave pgvector only → continued
✓ shown on attempt 2
hosting_comparison Self-hosting options for all three ✓ shown on attempt 1
recommendation A recommendation for the team ✓ shown on attempt 1Example: continuation alongside specialist routing and preflight
An unclear request gets clarifying questions before any work starts. A request that fits a specialist goes to that specialist, which continuation doesn't check. Everything else runs on your main agent, and continuation makes sure it finishes every part.
support_ops.py
1import asyncio
2
3from vidbyte import (
4 Agent,
5 JevAgent,
6 JevAgentSettings,
7 JevContinualSettings,
8 JevDoneCheck,
9 JevPreflightPreset,
10 JevRuntimeSettings,
11 JevSpecialist,
12)
13
14# search_tickets, update_article, and draft_reply stand in for your own @tool functions.
15
16release_writer = Agent(
17 name="release-writer",
18 system_prompt="You turn merged pull requests into clear, customer-facing release notes.",
19 provider="openai",
20 model_name="gpt-4.1",
21)
22
23ops = JevAgent(
24 JevAgentSettings(
25 name="support-ops",
26 system_prompt="You handle support operations: triage tickets, update the knowledge base, and draft replies.",
27 provider="openai",
28 model_name="gpt-4.1-mini",
29 tools=[search_tickets, update_article, draft_reply],
30 agents=(
31 JevSpecialist(
32 title="release_notes",
33 description="Writing or editing release notes and changelog entries from merged pull requests.",
34 agent=release_writer,
35 ),
36 ),
37 ),
38 JevRuntimeSettings(
39 preflight=(JevPreflightPreset.CLARITY,),
40 continual=JevContinualSettings(checks=(JevDoneCheck.MULTI_PART,)),
41 ),
42)
43
44async def main():
45 reply = await ops.arun(
46 "Find this week's tickets about failed CSV exports, update the export FAQ article, "
47 "and draft a reply I can send to each affected customer."
48 )
49 response = ops.response
50 if response.needs_clarification:
51 print("Jev asked first:\n", reply.content)
52 elif response.specialist:
53 print(f"{response.specialist} handled it; continuation does not apply")
54 else:
55 print(reply.content)
56 print("continuations:", response.continuations)
57
58asyncio.run(main())