This is an automated email from the ASF dual-hosted git repository.
gopidesupavan pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new 66b23a672b0 Document the dynamic `system_prompt` pattern for common-ai
agents (#69636)
66b23a672b0 is described below
commit 66b23a672b04e82da0821febfac333d04c530423
Author: Jason(Zhe-You) Liu <[email protected]>
AuthorDate: Sat Jul 11 00:47:17 2026 +0900
Document the dynamic `system_prompt` pattern for common-ai agents (#69636)
* Document dynamic system_prompt pattern for common-ai agents
* Address review nits in dynamic system_prompt example
---
providers/common/ai/docs/operators/agent.rst | 20 ++++++++++++
providers/common/ai/docs/operators/llm.rst | 5 +++
.../common/ai/example_dags/example_agent.py | 38 ++++++++++++++++++++++
3 files changed, 63 insertions(+)
diff --git a/providers/common/ai/docs/operators/agent.rst
b/providers/common/ai/docs/operators/agent.rst
index 6854ca4e948..63cf575c131 100644
--- a/providers/common/ai/docs/operators/agent.rst
+++ b/providers/common/ai/docs/operators/agent.rst
@@ -156,6 +156,26 @@ tasks can consume it.
:end-before: [END howto_agent_chain]
+.. _howto/operator:agent-dynamic-system-prompt:
+
+Dynamic System Prompt
+----------------------
+
+``system_prompt`` is a templated field, so instead of a static string it
+can be a Jinja expression that reads a value an earlier task already
+computed -- for example, tailoring the agent's instructions to a
+classification produced upstream.
+
+.. exampleinclude::
/../../ai/src/airflow/providers/common/ai/example_dags/example_agent.py
+ :language: python
+ :start-after: [START howto_agent_dynamic_system_prompt]
+ :end-before: [END howto_agent_dynamic_system_prompt]
+
+Open the **Rendered Template** tab on the task instance to see the
+substituted ``system_prompt`` after Jinja fills in ``classify``'s XCom
+values.
+
+
Multi-turn Sessions
-------------------
diff --git a/providers/common/ai/docs/operators/llm.rst
b/providers/common/ai/docs/operators/llm.rst
index 1f5a375ca90..28187d1c183 100644
--- a/providers/common/ai/docs/operators/llm.rst
+++ b/providers/common/ai/docs/operators/llm.rst
@@ -186,6 +186,11 @@ to process a list of items in parallel:
:start-after: [START howto_decorator_llm_pipeline]
:end-before: [END howto_decorator_llm_pipeline]
+.. seealso::
+ :ref:`Dynamic System Prompt <howto/operator:agent-dynamic-system-prompt>`
--
+ ``system_prompt`` is templated identically on ``@task.llm``, so the same
+ upstream-XCom pattern applies here.
+
Human-in-the-Loop Approval
--------------------------
diff --git
a/providers/common/ai/src/airflow/providers/common/ai/example_dags/example_agent.py
b/providers/common/ai/src/airflow/providers/common/ai/example_dags/example_agent.py
index 787b0d6dce2..e294260ca31 100644
---
a/providers/common/ai/src/airflow/providers/common/ai/example_dags/example_agent.py
+++
b/providers/common/ai/src/airflow/providers/common/ai/example_dags/example_agent.py
@@ -301,3 +301,41 @@ def example_agent_session():
# [END howto_agent_session]
example_agent_session()
+
+
+# ---------------------------------------------------------------------------
+# 9. Dynamic system prompt: template system_prompt from an upstream task's XCom
+# ---------------------------------------------------------------------------
+
+
+# [START howto_agent_dynamic_system_prompt]
+@dag(tags=["example"])
+def example_agent_dynamic_system_prompt():
+ @task
+ def classify(ticket: str) -> dict:
+ category = "shipping" if "order" in ticket.lower() else "other"
+ return {"priority": "high", "category": category}
+
+ @task.agent(
+ llm_conn_id="pydanticai_default",
+ # system_prompt is a templated field -- Jinja renders it at task-run
+ # time, pulling the classification an upstream task already computed.
+ system_prompt=(
+ "You are handling a {{
ti.xcom_pull(task_ids='classify')['priority'] }}-priority "
+ "'{{ ti.xcom_pull(task_ids='classify')['category'] }}' ticket. "
+ "Draft a concise, friendly reply."
+ ),
+ )
+ def draft_reply(ticket: str, triage: dict) -> str:
+ # `triage` creates the task dependency; its content also flows into
+ # system_prompt via Jinja above. The returned string is the *prompt*
+ # sent to the agent -- the drafted reply is this task's XCom output.
+ return f"Draft a reply for: {ticket}"
+
+ ticket = "Where is my order? It still hasn't shipped."
+ draft_reply(ticket, classify(ticket))
+
+
+# [END howto_agent_dynamic_system_prompt]
+
+example_agent_dynamic_system_prompt()