Skip to content

examples: add ModelBehaviorError handling patterns and self-healing agent - #3669

Closed
tahirkhan05 wants to merge 2 commits into
openai:mainfrom
tahirkhan05:examples/model-behavior-error-patterns
Closed

examples: add ModelBehaviorError handling patterns and self-healing agent#3669
tahirkhan05 wants to merge 2 commits into
openai:mainfrom
tahirkhan05:examples/model-behavior-error-patterns

Conversation

@tahirkhan05

@tahirkhan05 tahirkhan05 commented Jun 21, 2026

Copy link
Copy Markdown

Adds two new examples to examples/agent_patterns/ that address the common
question of what to do when the model calls a nonexistent tool or produces
invalid output (ModelBehaviorError). Closes #325.

Changes

model_behavior_error_handling.py

Three practical patterns for handling ModelBehaviorError:

  1. Return a safe fallback value — for best-effort tasks where a graceful default is acceptable
  2. Log and re-raise with enriched context — for production pipelines needing structured error reporting
  3. Retry with a fallback agent — hand the same task to a more reliable model when the primary misbehaves

self_healing_agent.py

A self-healing loop that catches ModelBehaviorError, appends the error as a
correction to the conversation, and retries up to MAX_SELF_HEALS times —
giving the model a chance to fix its own mistake without restarting the run
from scratch. Useful for long-running tasks where restarting is expensive.

examples/agent_patterns/README.md

Documents both new patterns alongside the existing ones.

Testing

python -m examples.agent_patterns.model_behavior_error_handling
python -m examples.agent_patterns.self_healing_agent

Note: This PR is complementary to PRs #2957 and #3402, not a replacement. Those PRs propose adding retry logic inside the SDK core. This PR shows developers how to handle ModelBehaviorError in their own application code today, using patterns that work with the current SDK regardless of whether a built-in retry mechanism is added.

…gent

Adds two new examples to examples/agent_patterns/ that address the common
question of what to do when the model calls a nonexistent tool or produces
invalid output (ModelBehaviorError), referenced in issue 325.

model_behavior_error_handling.py:
  Three practical patterns for handling ModelBehaviorError:
  1. Return a safe fallback value for best-effort tasks.
  2. Log and re-raise with enriched context for production pipelines.
  3. Retry the same task with a more reliable fallback agent.

self_healing_agent.py:
  A self-healing loop that catches ModelBehaviorError, appends the error
  as a correction to the conversation, and retries up to MAX_SELF_HEALS
  times. This gives the model a chance to fix its own mistake without
  restarting the full run from scratch.

Also updates examples/agent_patterns/README.md to document both patterns.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7dcc5797c5

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

# Build a fresh input that includes the correction.
# We restart from the original task plus the correction note so the
# model has full context without the broken tool call in its history.
messages = f"{task}\n\n[System note: {correction}]"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve prior turns during self-heal retries

When ModelBehaviorError is raised after the run has already completed earlier model/tool turns, this resets the next attempt to only the original task plus the latest correction, discarding the history available on exc.run_data. In the long-running/expensive-task scenario this example advertises, copied code will rerun prior work and any tool side effects on every heal instead of continuing from the failed run with the completed turns preserved.

Useful? React with 👍 / 👎.

Previously the retry loop discarded all completed turns and restarted
from the original task string, causing prior tool calls to be re-run
on every heal attempt (including any tool side effects).

Now the retry builds the next input from exc.run_data.new_items — the
list of RunItems completed before the error — and appends only the
correction message. This preserves the conversation history and avoids
re-running prior work, which is the main point of the self-healing
pattern for long-running tasks.

Falls back to full restart if exc.run_data is None (should not occur in
practice, but defensive).
@tahirkhan05

Copy link
Copy Markdown
Author

Addressed the Codex's review feedback.

The previous implementation discarded completed turns on each retry and restarted from the original task string, which would re-run prior tool calls (and their side effects) on every heal attempt.

The updated implementation builds the next input from exc.run_data.new_items, the RunItem list of everything completed before the error, and appends only the correction message. This preserves the conversation history and avoids redundant work, which is the core value of the self-healing pattern for long-running tasks.

Falls back to a full restart if exc.run_data is None (defensive, should not occur in practice).

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e7d840a5be

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

)

if completed_items:
input = completed_items + [correction]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the original run input on retries

When a failure happens after at least one completed turn, new_items contains only the items produced by this run while RunErrorDetails.input holds the user input separately, so this retry starts the next run with assistant/tool items plus the correction but without the original task. In this version the fresh issue is that the attempted fix now preserves generated turns but drops the run input, and on later heals can also drop prior retry context; build the retry from exc.run_data.input plus the converted new_items before appending the correction.

Useful? React with 👍 / 👎.

@seratch seratch added the wontfix This will not be worked on label Jun 22, 2026
@seratch

seratch commented Jun 22, 2026

Copy link
Copy Markdown
Member

Thanks for sharing the idea, but we don't plan to add these examples to this repo. Please feel free to host them in your own repo.

@seratch seratch closed this Jun 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

wontfix This will not be worked on

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Retry mechanism for ModelBehaviorError

2 participants