Skip to content

Add time_budget value for gen_ai.agent.finish_reason - #267

Closed
Nik-Reddy wants to merge 5 commits into
open-telemetry:mainfrom
Nik-Reddy:feat/gen-ai-agent-finish-reason-time-budget
Closed

Nik-Reddy wants to merge 5 commits into
open-telemetry:mainfrom
Nik-Reddy:feat/gen-ai-agent-finish-reason-time-budget

Conversation

@Nik-Reddy

Copy link
Copy Markdown
Member

Summary

Draft follow-up to #238 for issue #171.

This PR is intentionally a placeholder for the next focused follow-up: adding time_budget as a well-known value for gen_ai.agent.finish_reason.

Planned scope

  • Add time_budget to the gen_ai.agent.finish_reason well-known values.
  • Document it as the value for agent loop termination caused by an implementation-defined wall-clock budget or timeout.
  • Add one reference scenario, likely using CrewAI if it remains the cleanest public SDK timeout boundary.
  • Regenerate docs, schema snapshot, and reference reports.

Out of scope

This follow-up will not include handoff, tool_failure, cancelled, error, max_tokens, or budget sub-attributes. Those still need separate span-scope, precedence, or SDK-boundary discussion.

Refs #171.
Follows #238.

Nik-Reddy and others added 5 commits June 8, 2026 13:13
Introduces gen_ai.agent.finish_reason as a conditionally-required attribute
on the invoke_agent.client and invoke_agent.internal spans, with an initial
open enum containing three values, listed in alphabetical order to match
the repo's well-known-values rendering: completed, guardrail, max_iterations.
This is the agent-loop equivalent of the existing gen_ai.response.finish_reasons
attribute on per-LLM-call spans, which records only why a single completion
stopped generating.

The three values are the cleanest, SDK-detectable loop-termination signals
from the discussion on issue open-telemetry#171, with completed included so the attribute
carries meaningful information on the success path as well. The remaining
values from the issue discussion (handoff, tool_failure, cancelled, error,
time_budget) raise additional span-scope, exception-ordering, or
framework-specific questions and are intentionally deferred to follow-up
PRs so this change stays small and focused.

SDK source citations the maintainer can verify against the openai-agents
version pinned in reference/scenarios/openai-agents/pyproject.toml
(openai-agents 0.17.4):

- max_iterations: MaxTurnsExceeded exception class at
  src/agents/exceptions.py L56, raised from src/agents/run.py L1081 when
  Runner.run exceeds the max_turns budget.
- guardrail: InputGuardrailTripwireTriggered and
  OutputGuardrailTripwireTriggered exception classes at
  src/agents/exceptions.py L121 and L134, raised from
  src/agents/run_internal/guardrails.py L139 (input) and L174 (output).

Reference scenarios updated to exercise the attribute on both span
variants:

- openai-agents (invoke_agent.client): exercises both termination paths.
  run_agent sets finish_reason=completed after Runner.run returns
  normally; run_agent_max_iterations runs the same agent with
  max_turns=1, catches MaxTurnsExceeded, and sets
  finish_reason=max_iterations on the agent span.
- pydantic-ai (invoke_agent.internal): sets finish_reason=completed on
  the agent span after the chat operation returns.
- azure-ai-foundry (invoke_agent.client): sets finish_reason=completed
  on the success path inside the try block, so the value is recorded
  only when the invocation does not raise.

This covers both the client and internal invoke_agent span variants and
spans three different vendor SDKs (OpenAI, Pydantic, Microsoft Azure).

The registry note for the attribute is written in vendor-neutral terms.
SDK-specific source citations live in this commit message and in the PR
description; the spec text itself describes the framework-agnostic
pattern only. The conditionally_required condition is worded as
"when the agent loop has terminated and the termination reason is known"
so the attribute is omitted when the instrumentation cannot map the
termination to one of the listed values.

Refs: open-telemetry#171
Co-authored-by: Mike Goldsmith <goldsmith.mike@gmail.com>
@trask

trask commented Jun 10, 2026

Copy link
Copy Markdown
Member

Hi! As part of #275, this repository switched to Towncrier changelog fragments to reduce merge conflicts in CHANGELOG.md.

Please move this PR's changelog entry out of CHANGELOG.md and into this Towncrier fragment:

Create changelog.d/267.enhancement.md containing the change log entry, e.g.:

Add `gen_ai.agent.finish_reason` attribute on agent invocation spans (`invoke_agent.client`, `invoke_agent.internal`) with initial enum values `completed`, `guardrail`, and `max_iterations`. Records why the agent loop terminated; complements per-LLM-call `gen_ai.response.finish_reasons`. ([#171](https://github.com/open-telemetry/semantic-conventions-genai/issues/171))

After adding the fragment, please remove this PR's direct edit to CHANGELOG.md. Towncrier will add the PR link from the fragment filename when release notes are generated.

Thanks!

@opentelemetry-pr-dashboard

opentelemetry-pr-dashboard Bot commented Jul 18, 2026 •

Copy link
Copy Markdown

Pull request dashboard status

Waiting on the author · refreshed 2026-08-20 16:07 UTC

Move out of draft to request review.

Status above doesn't look right?
  • Just replied or pushed? Anything around or after the refresh time above may not be picked up yet — give it a few minutes.
  • Anything look wrong? Report it with what you expected; it helps us improve the dashboard.

@Nik-Reddy

Copy link
Copy Markdown
Member Author

Closing this in favor of the direction #238 landed on. gen_ai.agent.finish_reason was removed during review and replaced with gen_ai.agent.invocation.status (completed only); failure and termination causes, including a timeout, are represented via error.type on the span rather than a dedicated enum value. That makes the planned time_budget value unnecessary. If a CrewAI timeout reference scenario is still wanted, that would be a small independent follow-up, not a semconv change.

@Nik-Reddy Nik-Reddy closed this Aug 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants