Goal Engineering

Turn vague objectives into structured, measurable goals — then verify agent output against them

Goal Engineering turns a vague objective into a structured, measurable goal, then verifies agent output against it.

Diagram

📋 Statement

🎯 GoalEngineer

🧠 Goal
criteria + constraints

⚖️ verify

✅ Result
score + achieved

Quick Start

  1. Engineer and verify a goal

    Engineer a goal, run your agent against it, then verify the output:

    Python

    python
    from praisonaiagents import Agent, GoalEngineer
    
    agent = Agent(name="Summariser", instructions="Summarise the input")
    engineer = GoalEngineer()
    goal = engineer.engineer("Summarise the report in under 100 words")
    
    output = agent.start(goal.to_prompt())
    result = engineer.verify(goal, output)
    print(result.score, result.achieved)

    TypeScript

    typescript
    import { Agent, GoalEngineer } from 'praisonai';
    
    const agent = new Agent({ name: 'Summariser', instructions: 'Summarise the input' });
    const engineer = new GoalEngineer();
    const goal = await engineer.engineer('Summarise the report in under 100 words');
    
    const output = await agent.start(goal.toPrompt());
    const result = await engineer.verify(goal, output);
    console.log(result.score, result.achieved);
  2. Explicit criteria + constraints

    Provide your own criteria and constraints to skip LLM decomposition:

    python
    from praisonaiagents import GoalEngineer
    
    engineer = GoalEngineer(auto_decompose=False)
    goal = engineer.engineer(
        "Summarise the report",
        criteria=["Under 100 words", "Preserves key findings"],
        constraints=["No hallucinations"],
    )
  3. Full control with GoalConfig

    Tune the model, criteria count, and pass threshold:

    python
    from praisonaiagents import GoalEngineer, GoalConfig
    
    engineer = GoalEngineer(config=GoalConfig(
        model="gpt-4o",
        max_criteria=3,
        threshold=7.5,
    ))

How It Works

A statement is decomposed into criteria, the agent runs, and the output is scored by the same Judge used across evaluation.

Diagram
JudgeAgentLLMGoalEngineerUserJudgeAgentLLMGoalEngineerUserengineer(statement)decompose (auto_decompose)success criteriaGoalstart(goal.to_prompt())outputverify(goal, output)score output vs criteriascore + reasoningGoalVerificationResult
StepWhat happens
engineerBuilds a Goal from a statement. Uses supplied criteria, or the LLM proposes measurable ones when auto_decompose=True.
to_promptRenders the goal, criteria, and constraints as an instruction block for any agent.
verifyReuses the unified Judge to score the output. A score at/above threshold marks the goal achieved.

A judge failure is inconclusive — criteria stay pending and achieved=False, never a real unmet. The result carries an independent snapshot of criteria, so mutating it never corrupts the goal.


Configuration Options

OptionTypeDefaultDescription
modelOptional[str]os.getenv("OPENAI_MODEL_NAME", "gpt-4o-mini")LLM model used for decomposition/verification
max_criteriaint5Maximum success criteria auto-generated
thresholdfloat8.0Score (0–10) at/above which the goal is achieved
auto_decomposeboolTrueAuto-generate criteria via the LLM
verboseboolFalseEnable verbose logging

GoalConfig follows the PraisonAI convention: False = disabled, True = defaults, GoalConfig(...) = custom.

Goal Module Reference

Full Python API for the praisonaiagents package, including the goal exports


Data Model

GoalEngineer works with three dataclasses, all importable from praisonaiagents.

SuccessCriterion

A single measurable condition that contributes to achieving a goal.

FieldTypeDefaultDescription
descriptionstr—What must be true for this criterion to be met
idstr8-char UUIDUnique identifier
weightfloat1.0Relative importance when scoring the goal
statusLiteral["pending", "met", "unmet"]"pending"Current status
notesstr""Notes from verification

Methods: to_dict(), from_dict(data) (classmethod).

Goal

A goal exposes two computed properties in addition to its fields.

PropertyTypeDescription
progressfloatWeighted fraction of criteria whose status == "met", clamped to [0.0, 1.0]. Non-positive weights count as 0; when total weight is 0, criteria count equally.
is_achievedboolTrue when there is at least one criterion and all criteria are met

GoalVerificationResult

The result returned by verify().

FieldTypeDescription
goal_idstrThe verified goal’s id
scorefloatOverall score in 0.0–10.0
achievedboolWhether the goal is considered achieved (score >= config.threshold)
criteriaList[SuccessCriterion]Independent snapshot of the goal’s criteria with updated statuses; mutating this list does not affect the original Goal
reasoningstrJudge explanation, or "Verification unavailable: …" when the judge fell through

Method: to_dict().


Common Patterns

Weight criteria by importance and track weighted progress:

python
from praisonaiagents import GoalEngineer

engineer = GoalEngineer(auto_decompose=False)
goal = engineer.engineer("Ship the release notes")
goal.add_criterion("Covers every merged PR", weight=3.0)
goal.add_criterion("Reads clearly", weight=1.0)

print(goal.progress)  # fraction of weighted criteria met, clamped to [0.0, 1.0]

progress is the fraction of weighted criteria currently met, clamped to [0.0, 1.0]. Non-positive weights count as 0; when total weight is 0, criteria count equally.

Reuse one engineered goal across multiple agents via to_prompt():

python
from praisonaiagents import Agent, GoalEngineer

engineer = GoalEngineer()
goal = engineer.engineer("Draft a launch email under 150 words")

drafter = Agent(name="Drafter", instructions="Write marketing copy")
editor = Agent(name="Editor", instructions="Tighten and proofread")

draft = drafter.start(goal.to_prompt())
final = editor.start(goal.to_prompt() + f"\n\nDraft:\n{draft}")

Persist a goal with to_dict() and restore it with from_dict():

python
import json
from praisonaiagents import Goal, GoalEngineer

goal = GoalEngineer().engineer("Summarise the report")
saved = json.dumps(goal.to_dict())

restored = Goal.from_dict(json.loads(saved))

Best Practices

Prefer explicit criteria for tests

Pass your own criteria (with auto_decompose=False) when you need deterministic, repeatable checks. Let auto_decompose propose criteria while you explore a new goal.

Tune the threshold deliberately

threshold defaults to 8.0, which is strict. Lower it in GoalConfig when a goal tolerates partial success, and review the value the same way you review test assertions.

Use constraints for hard rules

Add constraints for safety and format rules that must never be violated. They render inside to_prompt(), so the agent sees them alongside the goal.

Treat pending as retry, not failure

A pending status in GoalVerificationResult means the judge was unavailable — retry the verification. It is not the same as an unmet criterion.


Related