Skip to content

feat(telemetry): emit system prompt on chat spans per GenAI semconv#1818

Open
sanjeed5 wants to merge 2 commits intostrands-agents:mainfrom
sanjeed5:feat/chat-span-system-prompt
Open

feat(telemetry): emit system prompt on chat spans per GenAI semconv#1818
sanjeed5 wants to merge 2 commits intostrands-agents:mainfrom
sanjeed5:feat/chat-span-system-prompt

Conversation

@sanjeed5
Copy link

@sanjeed5 sanjeed5 commented Mar 5, 2026

Motivation

Observability backends that render per-LLM-call conversation history are missing the system prompt on chat spans. Currently, start_model_invoke_span emits gen_ai.user.message, gen_ai.assistant.message, gen_ai.tool.message, and gen_ai.choice events, but the system prompt is never included even though it is sent to the model on every call.

Per OpenTelemetry GenAI semantic conventions, system instructions provided separately from chat history (which is exactly how Strands handles them via agent.system_prompt / agent._system_prompt_content) should be recorded using:

  • gen_ai.system.message event (v1.36 legacy conventions)
  • gen_ai.system_instructions attribute on gen_ai.client.inference.operation.details event (latest experimental conventions)

Related: #822, #1452

Public API Changes

start_model_invoke_span gains two optional keyword arguments with None defaults:

# Before
tracer.start_model_invoke_span(messages=messages, parent_span=span, model_id=model_id)

# After — system prompt now included on the chat span
tracer.start_model_invoke_span(
    messages=messages,
    parent_span=span,
    model_id=model_id,
    system_prompt=agent.system_prompt,
    system_prompt_content=agent._system_prompt_content,
)

No breaking changes. Callers that omit the new params get identical behavior as before.

Type of Change

New feature

Testing

  • Updated test_start_model_invoke_span to verify gen_ai.system.message event is emitted before conversation messages.

  • Updated test_start_model_invoke_span_latest_conventions to verify gen_ai.system_instructions appears on the details event.

  • Added test_start_model_invoke_span_without_system_prompt for backward-compatibility regression.

  • Added test_start_model_invoke_span_with_system_prompt_content to verify content block priority.

  • Updated test_event_loop_cycle_creates_spans to assert system prompt kwargs are forwarded.

  • I ran hatch run prepare (fmt + lint + tests pass)

Checklist

  • I have read the CONTRIBUTING document
  • I have added necessary tests that prove my fix is effective or my feature works
  • I have updated the documentation accordingly
  • I have added an appropriate example to the documentation to outline the feature, or no new docs are needed
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

System prompt was missing from chat (model invoke) span events, so
observability backends could not render the full conversation context
on individual LLM calls.

Legacy mode (v1.36): emits a gen_ai.system.message span event before
the conversation message events.

Latest experimental mode: emits gen_ai.system_instructions on the
gen_ai.client.inference.operation.details event, keeping it separate
from gen_ai.input.messages per the spec guidance that system
instructions provided separately from chat history should use
gen_ai.system_instructions.

Backwards compatible: new optional params default to None.
…-prompt

# Conflicts:
#	tests/strands/telemetry/test_tracer.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant