PromptisePromptise
Docs
GitHub
Promptise - AI Framework LogoPromptise

The foundation layer for agentic intelligence. Build, secure and operate autonomous AI systems with Promptise Foundry.

pip install promptise

[01] Foundry

  • MCPcast
  • The Promptise Agent
  • Reasoning Engine
  • MCP
  • Agent Runtime
  • Prompt Engineering
  • Execution Engine
  • Agent Identity

[02] Resources

  • Documentation
  • GitHub
  • Guides
  • Learning Paths
  • Questions

[03] Company

  • About
  • Terms of Service
  • Privacy Policy
  • Cookie Policy
  • Subprocessors

© 2026 Promptise by Manser Ventures. All rights reserved.

Open source · Python

← Guides> Runtime, triggers and deployment

Goal-Driven AI Agents: Missions With an LLM Judge

Give an AI agent a goal and let an LLM judge decide when it is done: success criteria, confidence thresholds, limits and costs. Runnable code, real output.

Level
Intermediate
Reading time
18 min
Published
Oct 19, 2026
Last updated
Oct 19, 2026
Tested with
Promptise 1.4.3
By
Promptise Team
  • Agent Runtime
  • LLM-as-a-Judge
  • Deployment
Contents · 16 sections↓
  1. 01How do you make an AI agent work toward a goal until it is done?
  2. 02How goal-driven agent missions work
  3. 03When to use a mission (and when not to)
  4. 04What you need
  5. 05Step 1: Define the mission
  6. 06Step 2: Write success criteria a judge can check
  7. 07Step 3: Test the mission logic without a model
  8. 08Step 4: Run a mission with an LLM judge
  9. 09Step 5: Control a mission over the API
  10. 10Step 6: Choose the judge model and control its cost
  11. 11The complete example
  12. 12Running it in production
  13. 13Common problems and fixes
  14. 14Limitations
  15. 15Frequently asked questions
  16. 16Next steps

A goal-driven AI agent keeps working on an objective across many runs until it is done, and something other than the agent decides when that is. Most agents answer one request and stop. A goal-driven agent migrates tables one per run, researches until a quality bar is met, or watches a rollout until it is stable. This guide shows how to give an agent a mission with Promptise Foundry, how an LLM judge evaluates success criteria after each run, and how to keep the judge accurate, cheap and bounded.

[01]

How do you make an AI agent work toward a goal until it is done?

Give the agent an objective and success criteria, run it repeatedly on a trigger, and after each run ask a separate model, the judge, whether the criteria are met. Stop when the judge says yes with enough confidence, and fail the goal when a time or run limit is reached. In the Promptise agent runtime, a MissionConfig on the process does all of this:

Python
1
2
3
4
5
6
7
8
9
from promptise.runtime import MissionConfig

mission = MissionConfig(
    enabled=True,
    objective="Shortlist three names for a neighborhood bike repair shop",
    success_criteria="The agent's replies contain three distinct names, each with a one-line reason.",
    eval_model="openai:gpt-5-mini",
    max_invocations=5,
)

Key takeaways:

  • The agent doesn't grade itself. A judge model reads the evidence and returns achieved, confidence and reasoning.

  • Success criteria must be checkable from what the judge sees: recent replies, context state and the trigger, not tool results.

  • Confidence controls escalation. A judge that is unsure pauses the mission for a person.

  • Always set a limit. max_invocations or timeout_hours turns a mission that never finishes into a clean failure.

  • The judge costs one model call per evaluation. eval_every and the judge model set that cost.


[02]

How goal-driven agent missions work

A mission is a goal with a state. The agent sees the goal before every run, works on it, and a judge checks the result. The pattern is framework-neutral: it is an outer loop around a normal tool-calling agent, with an LLM-as-a-judge as the stop condition.

Text
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
                 trigger event
                      │
          mission completed or failed? ── yes ──▶ skip the run
                      │ no
          limit reached? (timeout_hours, max_invocations) ── yes ──▶ FAILED
                      │ no
   agent runs with a [Mission] block: objective, criteria, progress, last verdict
                      │ success
       run count % eval_every == 0 and mission ACTIVE?
                      │ yes
   judge model reads the evidence ──▶ {achieved, confidence, reasoning, progress_summary}
          │                         │                               │
     achieved                not achieved,                    not achieved,
          │                  confidence < threshold           confidence >= threshold
          ▼                         ▼                               ▼
     COMPLETED                   PAUSED                          ACTIVE
   (auto_complete stops     (no more judging until            (next run)
     the process)             someone resumes it)

A mission is in one of four MissionState values: ACTIVE, PAUSED, COMPLETED or FAILED. Each judge verdict is a MissionEvaluation with achieved, confidence (0.0 to 1.0), reasoning, progress_summary, the invocation_number it covers, a timestamp and a source ("llm"). The evidence the judge reads is a MissionEvidence bundle that the runtime builds after each run.

Confidence is the judge's confidence in its own verdict, not a progress bar. "Not achieved, confidence 0.95" means the judge is sure the work isn't done yet, and the mission continues. "Not achieved, confidence 0.4" means the judge can't tell, which is when a person should look.


[03]

When to use a mission (and when not to)

Situation

Mission?

Why

Work that takes many runs, such as one table or one source per run

Yes

The agent needs a goal that outlives a single run

"Done" is a judgment, such as "the summary covers all five topics"

Yes

A judge can read and decide

"Done" is a fact your code can check, such as a row count

Use your own check

A test is cheaper and exact; see the limitations section

One request, one answer

No

A normal agent run already ends when it answers

You only need a ceiling on spend

Use budgets

See AI agent cost control


[04]

What you need

  • Python 3.10 or later and Promptise Foundry 1.4.3 or later.

  • An OpenAI API key in OPENAI_API_KEY for step 4. The example uses openai:gpt-5-mini as both agent and judge, and the whole mission costs less than a cent. Steps 3 and 5 make no model calls.

  • About 20 minutes.

>_Terminal
pip install "promptise>=1.4.3"

[05]

Step 1: Define the mission

A mission is a MissionConfig on the process (or a mission: block in a .agent manifest, with the same fields). These are all its fields:

Field

Default

Effect

enabled

False

Creates the mission tracker for this process

objective

""

What the agent is trying to achieve; shown to the agent and the judge

success_criteria

""

How the judge decides it is achieved

eval_model

None

The judge model ID; None uses the process model

eval_every

1

Judge after every Nth successful run

confidence_threshold

0.7

A "not achieved" verdict below this pauses the mission and escalates

timeout_hours

0

Fail the mission after this many hours (0 = no limit)

max_invocations

0

Fail the mission after this many successful runs (0 = no limit)

auto_complete

True

Stop the process when the mission is completed

on_complete

None

Deprecated and ignored; setting it only emits a FutureWarning

escalation

None

Where a low-confidence verdict is sent

Before every run, the agent gets the mission as a system message: the objective, the criteria, the state, progress such as "2 invocations/5", and the last verdict. You don't have to repeat the goal in the instructions, but the instructions should still say how to do one unit of work.

on_complete is a trap: it looks like it chooses between stopping and suspending, but nothing reads it. Use auto_complete=False to keep the process running after completion. Its later runs are then skipped, because the mission is done.


[06]

Step 2: Write success criteria a judge can check

The judge can only grade what it sees. The runtime gives it:

  • the last 10 messages of the conversation buffer (the trigger messages and the agent's final replies), 500 characters each;

  • the context state, up to 1,000 characters;

  • the names of the last run's tool calls, with an argument hash, when health monitoring is on;

  • the trigger type and payload, up to 300 characters.

It doesn't see tool results. If the agent called validate_schema and the tool said "passed", the judge only knows the tool was called. Write criteria that point at evidence the judge can read:

Weak criteria

Why it fails

Better criteria

"The migration is done."

No observable test

"The agent's last reply lists all 8 tables with 'v2 validation passed'."

"High-quality research."

The judge invents its own bar

"The context key sources lists at least 5 URLs from different domains."

"All tickets are handled."

Old replies drop out after 10 messages

"The agent's latest reply states the open-ticket count, and it is 0."

Two habits make criteria reliable. First, ask the agent to restate progress in every reply, such as "Shortlist so far: A, B, C", so the latest reply carries the whole state. Second, when your own systems know the truth, write it into the context state (see AI agent state between runs) and point the criteria at that key. The judge trusts what it reads, and that includes the agent's own claims.


[07]

Step 3: Test the mission logic without a model

MissionTracker is the class the runtime uses. On its own it also accepts a success_check function, so you can watch the state machine with no model at all. The function returns True (achieved), False (not yet) or None (ask the judge):

Pythontracker_basics.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
"""Drive a MissionTracker by hand with a programmatic check. No model, no API key."""
import asyncio
import logging

from promptise.runtime import MissionConfig, MissionEvidence, MissionTracker

logging.disable(logging.WARNING)

config = MissionConfig(
    enabled=True,
    objective="Shortlist three names for a bike repair shop",
    success_criteria="Three distinct names, each with a one-line reason",
    max_invocations=5,
)


def three_names(evidence: MissionEvidence) -> bool | None:
    names = evidence.state.get("names", [])
    return len(set(names)) >= 3  # True = achieved, False = not yet, None = ask the judge


async def main():
    tracker = MissionTracker(config, process_id="namer", success_check=three_names)
    names = []
    for name in ["Spoke & Mend", "Chain Reaction", "Spoke & Mend", "Gear Garage"]:
        names.append(name)
        tracker.increment_invocation()  # AgentProcess does this after each successful run
        if not tracker.should_evaluate():
            continue
        evaluation = await tracker.evaluate(MissionEvidence(state={"names": names}), model=None)
        print(f"run {tracker.invocation_count}: achieved={evaluation.achieved} "
              f"confidence={evaluation.confidence} source={evaluation.source} "
              f"state={tracker.state.value}")
        if tracker.state.value != "active":
            break

    print("\nwhat the agent sees before its next run:")
    print(tracker.context_summary())

    print("\nmanual transitions:")
    other = MissionTracker(config, process_id="namer-2")
    other.pause()
    print("pause  ->", other.state.value)
    other.resume()
    print("resume ->", other.state.value)
    other.fail("Supplier list withdrawn")
    print("fail   ->", other.state.value, "| should_evaluate:", other.should_evaluate())


asyncio.run(main())
Output
run 1: achieved=False confidence=1.0 source=programmatic state=active
run 2: achieved=False confidence=1.0 source=programmatic state=active
run 3: achieved=False confidence=1.0 source=programmatic state=active
run 4: achieved=True confidence=1.0 source=programmatic state=completed

what the agent sees before its next run:
Objective: Shortlist three names for a bike repair shop
Success Criteria: Three distinct names, each with a one-line reason
Status: completed
Progress: 4 invocations/5
Last Evaluation: confidence=1.00 — Programmatic success check returned True
Progress Summary: Mission criteria met

manual transitions:
pause  -> paused
resume -> active
fail   -> failed | should_evaluate: False

The repeated name in run 3 kept the count at two, and run 4 completed the mission. The "what the agent sees" block is the text the runtime injects before each run. The manual transitions are the same ones the API calls in step 5. Note that a failed mission no longer evaluates.

success_check is available only when you drive MissionTracker yourself, for example in a test. AgentProcess creates its tracker without one, so a process always uses the LLM judge.


[08]

Step 4: Run a mission with an LLM judge

Now the real thing. The agent proposes one shop name per run, and a gpt-5-mini judge decides after each run whether three names with reasons exist. The script listens for mission events and reads the verdicts back through the management API:

Pythonmission_agent.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
"""A goal-driven agent: gpt-5-mini works on a mission, a gpt-5-mini judge decides when it is done."""
import asyncio
import logging
import secrets

from promptise.events import CallbackSink, EventNotifier
from promptise.runtime import (
    AgentRuntime,
    JournalConfig,
    MissionConfig,
    OrchestrationAPI,
    OrchestrationClient,
    ProcessConfig,
    TriggerEvent,
)

logging.disable(logging.WARNING)

INSTRUCTIONS = (
    "You are building a shortlist of names for a neighborhood bike repair shop. "
    "Each run, propose exactly one new name you have not proposed before, with a "
    "one-line reason. Reply on one line: <name> - <reason>."
)

MISSION = MissionConfig(
    enabled=True,
    objective="Shortlist three names for a neighborhood bike repair shop",
    success_criteria=(
        "The agent's replies so far contain at least three distinct shop names, "
        "each with a one-line reason."
    ),
    eval_model="openai:gpt-5-mini",  # the judge; None would reuse the process model
    eval_every=1,                    # judge after every successful run
    confidence_threshold=0.7,        # a less sure "not yet" pauses the mission
    max_invocations=5,               # fail the mission after five runs
    auto_complete=True,              # stop the process once the judge says achieved
)

mission_events: asyncio.Queue = asyncio.Queue()


async def on_event(event):
    await mission_events.put(event)


async def main():
    notifier = EventNotifier([CallbackSink(on_event, events=[
        "mission.progress", "mission.complete", "mission.failed"])])
    runtime = AgentRuntime(event_notifier=notifier)
    process = await runtime.add_process("shop-namer", ProcessConfig(
        model="openai:gpt-5-mini",
        instructions=INSTRUCTIONS,
        journal=JournalConfig(level="checkpoint", backend="memory"),
        mission=MISSION,
    ))
    token = secrets.token_urlsafe(24)
    api = OrchestrationAPI(runtime, port=9100, auth_token=token)
    await api.start()
    await process.start()

    async with OrchestrationClient("http://127.0.0.1:9100", token=token) as client:
        for _ in range(MISSION.max_invocations):
            await process.inject(TriggerEvent(
                trigger_id="next", trigger_type="manual", payload={"request": "next name"}))
            event = await asyncio.wait_for(mission_events.get(), timeout=180)
            last = await client.get_journal("shop-namer", entry_type="invocation_result", limit=1)
            print(f"run {event.data.get('invocations')}: {last[0]['data']['response']}")
            print(f"  {event.event_type} confidence={event.data.get('confidence')}")
            if event.event_type != "mission.progress":
                break

        await asyncio.sleep(1)
        mission = (await client.get_mission("shop-namer"))["mission"]
        print(f"\nmission state: {mission['state']} after {mission['invocation_count']} runs")
        for number, evaluation in enumerate(mission["evaluations"], start=1):
            print(f"judge {number}: achieved={evaluation['achieved']} "
                  f"confidence={evaluation['confidence']}")
            print(f"  {evaluation['reasoning']}")
        print("process state:", (await client.get_process("shop-namer"))["state"])

    await process.stop()
    await api.stop()
    await notifier.stop()


asyncio.run(main())
Output
run 1: Pedal Patch - A friendly, memorable name that conveys quick, local fixes for every rider.
  mission.progress confidence=0.95
run 2: Spoke & Wrench - A classic, workshop-y name that highlights wheel and tool expertise with a friendly, artisanal feel.
  mission.progress confidence=0.92
run 3: Chain Reaction - A playful name that suggests quick, effective repairs keeping the neighborhood rolling.
  mission.complete confidence=0.95

mission state: completed after 3 runs
judge 1: achieved=False confidence=0.95
  The assistant has provided only one shop name with a one-line reason ('Pedal Patch'). The success criteria require at least three distinct names, each with a one-line reason, so the objective has not been met.
judge 2: achieved=False confidence=0.92
  I inspected the assistant replies in the conversation and found two distinct shop names with one-line reasons: "Pedal Patch - A friendly, memorable name that conveys quick, local fixes for every rider." and "Spoke & Wrench - A classic, workshop-y name that highlights wheel and tool expertise with a friendly, artisanal feel." The success criteria require at least three distinct names each with a one-line reason; only two are present, so the objective is not yet met.
judge 3: achieved=True confidence=0.95
  The assistant provided three distinct shop names and each reply included a one-line reason, matching the success criteria.
process state: stopped

How the run unfolded:

  • Runs 1 and 2: `mission.progress`. The judge said "not achieved" with confidence 0.95 and 0.92. Both are above the 0.7 threshold, so the mission stayed active. Its reasoning names what is missing.

  • Run 3: `mission.complete`. The judge found three distinct names with reasons. The mission moved to completed, and auto_complete=True stopped the process, as process state: stopped shows.

  • The verdicts are stored. GET /api/v1/processes/{name}/mission returns the state, the run count and every evaluation with its reasoning. When the process has a journal, each verdict is also written as a mission_evaluation entry.

The agent didn't need the earlier names in its instructions. The conversation buffer carried them from run to run, and the [Mission] block showed the judge's last summary.


[09]

Step 5: Control a mission over the API

Operators need to stop a mission that has gone wrong, hold it while they check something, and let it continue. The management API has a route for each, and an agent in open mode can also read its own mission:

Pythonmission_api.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
"""Pause, resume and fail a mission over the API, and see what check_mission returns. No model calls."""
import asyncio
import logging
import secrets

from promptise.runtime import (
    AgentRuntime,
    ExecutionMode,
    JournalConfig,
    MissionConfig,
    OrchestrationAPI,
    OrchestrationClient,
    ProcessConfig,
    TriggerEvent,
)
from promptise.runtime.meta_tools import create_meta_tools

logging.disable(logging.WARNING)


async def main():
    runtime = AgentRuntime()
    process = await runtime.add_process("migrator", ProcessConfig(
        model="openai:gpt-5-mini",
        instructions="Migrate the billing tables to the v2 schema, one table per run.",
        execution_mode=ExecutionMode.OPEN,  # adds the check_mission meta-tool
        journal=JournalConfig(level="none"),
        mission=MissionConfig(
            enabled=True,
            objective="Migrate all billing tables to the v2 schema",
            success_criteria="Every billing table reports 'v2 validation passed'",
            max_invocations=40,
            timeout_hours=12,
        ),
    ))
    token = secrets.token_urlsafe(24)
    api = OrchestrationAPI(runtime, port=9100, auth_token=token)
    await api.start()
    await process.start()

    tools = {tool.name: tool for tool in create_meta_tools(process)}
    print("check_mission returns:")
    print(await tools["check_mission"].ainvoke({}))

    async with OrchestrationClient("http://127.0.0.1:9100", token=token) as client:
        print("\npause  ", await client.pause_mission("migrator"))
        print("state  ", (await client.get_mission("migrator"))["mission"]["state"])
        print("resume ", await client.resume_mission("migrator"))
        print("fail   ", await client.fail_mission("migrator", reason="Schema v2 rolled back"))
        mission = (await client.get_mission("migrator"))["mission"]
        print("state  ", mission["state"], "| evaluations:", mission["evaluations"])

        await process.inject(TriggerEvent(trigger_id="tick", trigger_type="manual", payload={}))
        await asyncio.sleep(1)
        info = await client.get_process("migrator")
        print("\nafter a trigger:", {k: info[k] for k in ("state", "mission_state", "invocation_count")})

    await process.stop()
    await api.stop()


asyncio.run(main())
Output
check_mission returns:
Objective: Migrate all billing tables to the v2 schema
Success Criteria: Every billing table reports 'v2 validation passed'
Status: active
Progress: 0 invocations/40, 0.0/12.0 hours

pause   {'name': 'migrator', 'mission_paused': True}
state   paused
resume  {'name': 'migrator', 'mission_resumed': True}
fail    {'name': 'migrator', 'mission_failed': True, 'reason': 'Schema v2 rolled back'}
state   failed | evaluations: []

after a trigger: {'state': 'running', 'mission_state': 'failed', 'invocation_count': 0}

Route

Client method

Effect

Text
GET /api/v1/processes/{name}/mission

get_mission(name)

State, objective, run count, verdicts

POST .../mission/pause

pause_mission(name)

Stop judging; runs continue

POST .../mission/resume

resume_mission(name)

Judge again (only from paused)

POST .../mission/fail

fail_mission(name, reason)

Mark failed; later runs are skipped

Text
PATCH /api/v1/processes/{name}/mission

update_mission(name, **fields)

Change fields such as max_invocations, effective at once

A paused mission doesn't pause the agent. The process keeps running its triggers, and only the judging stops. To stop the agent too, suspend the process. A failed mission leaves the process running while it skips every run, as the last line shows, so stop it when you fail the mission. A manual fail doesn't emit mission.failed; that event comes only from the limits. Routes, tokens and the rest of the API are covered in the AI agent control API.

check_mission is the agent's side of this. In open mode (execution_mode=ExecutionMode.OPEN) the agent gets it as a meta-tool, and it returns the same block the runtime injects: objective, criteria, state, progress and the last verdict. It doesn't return the full verdict history. Open mode gives the agent many other powers, so read self-modifying AI agents before you turn it on just for this tool.


[10]

Step 6: Choose the judge model and control its cost

Every evaluation is one call to the judge with up to about 7,000 characters of evidence, roughly 2,000 input tokens, plus a short JSON answer. With eval_every=1, a mission makes about two model calls per run: the agent's and the judge's. Three levers set the cost:

  • `eval_every`. Judge only as often as progress can change the answer. An agent that migrates one of 40 tables per run can be judged every 5 runs. The mission then completes up to 4 runs late, and those runs do real work, so make sure extra work is harmless.

  • `eval_model`. The judge's task is reading and comparing, which small models do well. gpt-5-mini judged correctly in step 4. Use a stronger judge when the criteria need reasoning, such as checking a calculation, and test it on transcripts where the answer is known.

  • `max_invocations` and `timeout_hours`. They bound the total, judge calls included.

The judge must answer with JSON. When the call fails or the reply doesn't parse, the runtime records "not achieved", confidence 0.5 and reasoning starting with Evaluation failed:. Below the default threshold of 0.7, that pauses the mission. A judge model that wraps JSON in prose will keep pausing your missions, so try a candidate judge on a few runs before you deploy it.

confidence_threshold is the other dial. Raise it toward 0.9 when a wrong "keep going" is expensive and you want a person to look at any doubt. Lower it toward 0.5 for low-stakes missions where pauses would only add work for the team.


[11]

The complete example

The project has three files: the tracker test from step 3, the mission from step 4 and the API demo from step 5.

Text
mission-demo/
├── tracker_basics.py   # state machine with a programmatic check (no model)
├── mission_agent.py    # gpt-5-mini agent and judge, events, verdicts over the API
└── mission_api.py      # pause, resume, fail, check_mission (no model calls)
>_Terminal
pip install "promptise>=1.4.3"
python tracker_basics.py
export OPENAI_API_KEY=sk-...
python mission_agent.py
python mission_api.py

In production the trigger is usually a cron schedule or a webhook rather than injected events. See AI agent cron jobs for a schedule that drives a mission one run at a time.


[12]

Running it in production

Always bound the mission

A mission without max_invocations or timeout_hours can run forever on a goal the agent can't reach. Set both. Only successful runs count toward max_invocations, and the timeout clock starts when the process object is created. Both limits are checked before each run and after its evaluation, so max_invocations=50 allows 50 runs and fails the mission right after the 50th unless that one completed it. For token and tool-call ceilings, add a budget as in AI agent cost control.

Route low-confidence verdicts to a person

A verdict below confidence_threshold pauses the mission and, when escalation is set, sends an EscalationTarget notification with the confidence and reasoning; escalation targets get their own guide. Subscribe to mission.progress, mission.complete and mission.failed events for dashboards, as step 4 does with a callback sink. For webhook and Slack delivery, see AI agent notifications.

Don't trust the agent's claims blindly

The judge reads the agent's replies, and an agent can claim work it didn't do. Trigger payloads reach the judge too, and they come from outside your system. For missions that matter, ground the criteria in state your own code writes after checking the facts, not in the agent's description of them. The runtime wraps trigger payloads as untrusted data for the agent; see prompt injection defense for the wider problem.

Plan for redeploys

The mission lives in process memory, and restarting the same process keeps it. The journal checkpoint includes the mission state, but nothing reads it back when a new OS process starts, so after a redeploy the mission begins again with zero runs, a fresh clock and no verdicts. A completed mission becomes active again. For long missions, record progress in context state, which the journal's replay can restore, and write criteria against that. Durable AI agent crash recovery covers what the journal restores.


[13]

Common problems and fixes

Symptom

Cause

Fix

Mission paused after the first evaluation

Judge reply wasn't valid JSON: confidence 0.5, below 0.7

Check the verdict's reasoning for Evaluation failed:; try another judge model

Mission paused, agent keeps running

Paused means "stop judging", not "stop running"

Suspend the process too, or resume the mission

Judge says "not achieved" although the work is done

The proof is in tool results, which the judge can't see

Have the agent restate results in its reply, or write them to state

Judge forgets work from early runs

It sees only the last 10 messages

Ask for a cumulative "so far" line in every reply

on_complete="suspend" has no effect

on_complete is deprecated and ignored

Use auto_complete

Process runs but every run is skipped

The mission is completed or failed

Stop the process, or start a new one with a new mission

Mission starts over after a redeploy

Mission state isn't restored from the journal

Keep progress in context state and criteria

Judge cost is higher than expected

eval_every=1 doubles model calls

Raise eval_every or use a smaller judge


[14]

Limitations

  • The runtime always uses an LLM judge. A programmatic success_check works only with MissionTracker used directly. For goals your code can verify exactly, check them yourself and fail or stop the process over the API.

  • The judge's view is narrow. Ten messages, truncated state and no tool results. Long or detail-heavy missions need criteria built around a summary.

  • No restore after a redeploy. See the production section.

  • One mission per process. To change the goal, patch objective and success_criteria, or deploy a new process.

  • `check_mission` shows only the last verdict, not the history. Read the history over the API.


[15]

Frequently asked questions

What is a goal-driven AI agent?

A goal-driven AI agent works toward an objective across many runs instead of answering one request. Each run does part of the work, and a separate check decides whether the goal is reached. In Promptise Foundry this is a mission: an objective, success criteria and an LLM judge that evaluates progress after each run and completes, pauses or fails the mission.

How does an LLM judge decide that an agent's goal is complete?

The judge receives the objective, the success criteria and evidence: recent replies, context state, tool call names and the trigger. It answers with JSON containing achieved, confidence, reasoning and a progress summary. The mission completes when achieved is true. A "not achieved" verdict below the confidence threshold pauses the mission for a person.

Which model should I use as the judge?

Start with a small, fast model such as gpt-5-mini, because the task is reading and comparing against criteria. Move to a stronger model when the criteria need reasoning, such as checking numbers. Whichever you choose, it must return valid JSON reliably, because a reply that doesn't parse counts as confidence 0.5 and pauses the mission at the default threshold.

How much does an LLM judge cost per mission?

One judge call per evaluation, with up to about 2,000 input tokens of evidence plus a short answer. With eval_every=1 that roughly doubles the model calls of the mission. Raise eval_every to judge less often, choose a small judge model, and set max_invocations so the total is bounded.

What happens when the judge is not confident?

When the judge says the goal isn't achieved and its confidence is below confidence_threshold (default 0.7), the mission moves to paused, and an escalation is sent if one is configured. The agent keeps running on its triggers, but no more evaluations happen until someone resumes the mission over the API.

How do I stop a mission that is going wrong?

Call POST /api/v1/processes/{name}/mission/fail with a reason, or fail_mission(name, reason) from the Python client. Later runs are skipped, but the process stays running, so stop it too. To hold a mission without failing it, pause it, and suspend the process if the agent itself should stop working.


[16]

Next steps

  • Drive a mission on a schedule: AI agent cron jobs.

  • Keep progress outside the conversation: AI agent state between runs.

  • Catch empty replies and failing runs on the same process: AI agent health monitoring.

  • Manage missions over HTTP: the AI agent control API.

  • See every governance feature together: the autonomous AI agent runtime.

  • Build an evaluation suite for the agent itself: how to evaluate AI agents in Python.

  • Reference: missions and meta-tools in the Promptise docs.

Contents

  1. 01How do you make an AI agent work toward a goal until it is done?
  2. 02How goal-driven agent missions work
  3. 03When to use a mission (and when not to)
  4. 04What you need
  5. 05Step 1: Define the mission
  6. 06Step 2: Write success criteria a judge can check
  7. 07Step 3: Test the mission logic without a model
  8. 08Step 4: Run a mission with an LLM judge
  9. 09Step 5: Control a mission over the API
  10. 10Step 6: Choose the judge model and control its cost
  11. 11The complete example
  12. 12Running it in production
  13. 13Common problems and fixes
  14. 14Limitations
  15. 15Frequently asked questions
  16. 16Next steps

Learning paths

Want more structure? Paths put guides in order, like a short course.

See the paths →

> Runtime, triggers and deployment

Related guides

All guides in this topic →
  • // 01Intermediate · 17 minAI Agent Secrets Management: Scoped, Expiring CredentialsManage AI agent secrets safely: scope credentials per agent, expire and rotate them, keep them out of prompts and logs, and audit each access. Real output.
  • // 02Intermediate · 19 minMCP Long-Running Tasks: Background Jobs in PythonRun slow MCP tools as background jobs in Python: submit, poll progress, retry failures and cancel, with a real agent, real runs and honest limits.
  • // 03Beginner · 15 minHow to Run, Debug and Deploy an AI Agent in PythonRun, debug and deploy a Python AI agent project with one command: a package.json-style manifest, live traces, a terminal UI, JSON logs and an API.
  • // 04Intermediate · 15 minDeploy AI Agents in Production: Long-Running Python AgentsRun an AI agent as a long-lived Python process: cron and webhook triggers, state between runs, a journal, budgets that pause it, and honest limits.
  • // 05Intermediate · 18 minHow to Deploy an AI Agent with Docker (2026 Guide)Deploy an AI agent with Docker: a Dockerfile, env config and secrets, health checks, graceful shutdown and docker compose with an MCP server. Tested.
  • // 06Intermediate · 17 minAI Agent Production Checklist: What to Check Before LaunchAn AI agent production checklist: security, approvals, guardrails, limits, cost, observability, evals, deployment and incident response, with code.

Keep going.

Browse every guide by topic and level, or follow a learning path that puts them in order.

All guidesLearning paths