Skip to content

Add message_history to AgentOperator for multi-turn agent sessions#68648

Merged
kaxil merged 1 commit into
apache:mainfrom
astronomer:agent-message-history
Jun 18, 2026
Merged

Add message_history to AgentOperator for multi-turn agent sessions#68648
kaxil merged 1 commit into
apache:mainfrom
astronomer:agent-message-history

Conversation

@kaxil

@kaxil kaxil commented Jun 17, 2026

Copy link
Copy Markdown
Member

AgentOperator (and the @task.agent decorator) ran a fresh, single-turn
conversation on every run. There was no supported way to seed a run with prior
turns or to persist the resulting transcript for the next run, so conversational
or iterative agents that resume a conversation across DAG runs could not be
expressed with the operator.

This adds an opt-in message_history parameter. When set, the operator seeds the
run with the prior turns and pushes the full post-run transcript to XCom (key
message_history) so the next run can resume. message_history=None (the
default) keeps the existing single-turn behavior unchanged, so there is no impact
on current users.

How it works

  • message_history accepts a list of pydantic-ai ModelMessage objects or their
    JSON form (str / bytes), and is a templated field. It is deserialized via
    ModelMessagesTypeAdapter and passed to run_sync(message_history=...) on both
    the durable and non-durable branches.
  • After the run, the transcript (result.all_messages()) is serialized and
    pushed to XCom under the key message_history.
  • An empty [] / "" starts a fresh session, so a templated
    {{ ti.xcom_pull(task_ids='ask', key='message_history', default='[]') }} works
    on the first run (no XCom yet) instead of failing to parse the string "None".

Usage

A multi-turn session brackets the agent with a load and a save task. Where the
transcript is stored (keyed by a session id, e.g. in object storage) is left to
the DAG:

https://github.com/astronomer/airflow/blob/3378a9c6c3c6e6fe4002a6ad8ccc5b3a08c2bd52/providers/common/ai/src/airflow/providers/common/ai/example_dags/example_agent.py#L224-L268

image image image image

Design notes

  • No storage abstraction, by design. The operator owns the round-trip
    (history in, transcript out); it does not own where a session is stored.
    Session keying is deployment-specific and belongs in the DAG, and keeping the
    surface this thin avoids committing the provider to a message-persistence
    protocol while the upstream ones are still settling.
  • message_history cannot be combined with enable_hitl_review (the operator
    raises at construction, mirroring the existing durable + HITL guard). The
    post-review transcript is not recoverable today (run_hitl_review returns only
    the final string), so emitting the pre-review transcript would silently drop the
    human-approved turns. This can be lifted once HITL surfaces the final history.

Gotchas

  • The transcript is cumulative and grows every turn. For long-running sessions,
    configure an object-storage XCom backend or trim older turns before feeding the
    history back, rather than passing the whole history unbounded.

@gopidesupavan gopidesupavan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

cool :)

AgentOperator and @task.agent ran a fresh single-turn conversation every time. Add an opt-in message_history parameter that seeds the run with prior turns and pushes the post-run transcript to XCom (key 'message_history') so the next run can resume. Default None keeps single-turn behavior unchanged. Storing the transcript under a session key stays the DAG's responsibility.
@kaxil kaxil force-pushed the agent-message-history branch from ec83203 to 8ab8b52 Compare June 18, 2026 00:26
@kaxil kaxil merged commit 531bfab into apache:main Jun 18, 2026
78 of 79 checks passed
@kaxil kaxil deleted the agent-message-history branch June 18, 2026 23:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants