Skip to content

Commit 72ecee9

Browse files
authored
Merge pull request #10 from pamelafox/workflows
Adding workflows for presentation
2 parents 4a98192 + f27b916 commit 72ecee9

25 files changed

Lines changed: 3439 additions & 277 deletions

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,17 +186,38 @@ You can run the examples in this repository by executing the scripts in the `exa
186186
| [agent_tool.py](examples/agent_tool.py) | An agent with a single weather tool. |
187187
| [agent_tools.py](examples/agent_tools.py) | A weekend planning agent with multiple tools. |
188188
| [agent_session.py](examples/agent_session.py) | In-memory sessions for multi-turn conversations with memory across messages. |
189+
| [agent_history_sqlite.py](examples/agent_history_sqlite.py) | Persistent chat history with a custom SQLite history provider for local file-based conversation persistence. |
189190
| [agent_history_redis.py](examples/agent_history_redis.py) | Persistent chat history with Redis for conversation history that survives restarts. |
191+
| [agent_memory_redis.py](examples/agent_memory_redis.py) | Long-term memory with RedisContextProvider, storing and retrieving conversational context from Redis. |
192+
| [agent_memory_mem0.py](examples/agent_memory_mem0.py) | Long-term memory with Mem0 OSS, extracting and recalling distilled user facts across sessions. |
190193
| [agent_supervisor.py](examples/agent_supervisor.py) | A supervisor orchestrating activity and recipe sub-agents. |
194+
| [agent_with_subagent.py](examples/agent_with_subagent.py) | Context isolation with sub-agents to keep prompts focused on relevant tools. |
195+
| [agent_without_subagent.py](examples/agent_without_subagent.py) | Context bloat example where one agent carries all tool schemas in a single prompt. |
196+
| [agent_summarization.py](examples/agent_summarization.py) | Context compaction via summarization middleware to reduce token usage in long conversations. |
191197
| [agent_middleware.py](examples/agent_middleware.py) | Agent, chat, and function middleware for logging, timing, and blocking. |
198+
| [agent_knowledge_aisearch.py](examples/agent_knowledge_aisearch.py) | Knowledge retrieval (RAG) using Azure AI Search with AgentFrameworkAzureAISearchRAG. |
192199
| [agent_knowledge_sqlite.py](examples/agent_knowledge_sqlite.py) | Knowledge retrieval (RAG) using a custom context provider with SQLite FTS5. |
200+
| [agent_knowledge_pg.py](examples/agent_knowledge_pg.py) | Knowledge retrieval (RAG) with PostgreSQL hybrid search (pgvector + full-text) using Reciprocal Rank Fusion. |
201+
| [agent_knowledge_pg_rewrite.py](examples/agent_knowledge_pg_rewrite.py) | Knowledge retrieval with query rewriting for multi-turn conversations over PostgreSQL. |
193202
| [agent_knowledge_postgres.py](examples/agent_knowledge_postgres.py) | Knowledge retrieval (RAG) with PostgreSQL hybrid search (pgvector + full-text) using Reciprocal Rank Fusion. |
194203
| [agent_mcp_remote.py](examples/agent_mcp_remote.py) | An agent using a remote MCP server (Microsoft Learn) for documentation search. |
195204
| [agent_mcp_local.py](examples/agent_mcp_local.py) | An agent connected to a local MCP server (e.g. for expense logging). |
196205
| [openai_tool_calling.py](examples/openai_tool_calling.py) | Tool calling with the low-level OpenAI SDK, showing manual tool dispatch. |
206+
| [workflow_rag_ingest.py](examples/workflow_rag_ingest.py) | A RAG ingestion pipeline using plain Python executors: fetch a document with markitdown, split into chunks, and embed with an OpenAI model. |
207+
| [workflow_agents.py](examples/workflow_agents.py) | A workflow with AI agents as executors: a Writer drafts content and a Reviewer provides feedback. |
208+
| [workflow_agents_sequential.py](examples/workflow_agents_sequential.py) | A sequential orchestration using `SequentialBuilder`: Writer and Reviewer run in order while sharing full conversation history. |
209+
| [workflow_agents_streaming.py](examples/workflow_agents_streaming.py) | The same Writer → Reviewer workflow using `run(stream=True)` to observe `executor_invoked`, `executor_completed`, and streaming `output` events in real-time. |
210+
| [workflow_conditional.py](examples/workflow_conditional.py) | A minimal workflow with conditional edges: the Reviewer routes to a Publisher (approved) or Editor (needs revision) based on a sentinel token. |
211+
| [workflow_conditional_structured.py](examples/workflow_conditional_structured.py) | The same conditional-edge routing pattern, but with structured reviewer output (`response_format`) for typed branch decisions instead of sentinel string matching. |
212+
| [workflow_conditional_state.py](examples/workflow_conditional_state.py) | A stateful conditional workflow with iterative revision loops: stores the latest draft in workflow state and publishes from that state after approval. |
213+
| [workflow_conditional_state_isolated.py](examples/workflow_conditional_state_isolated.py) | The stateful conditional workflow using a `create_workflow(...)` factory to build fresh agents/workflow per task for state isolation and thread safety. |
214+
| [workflow_switch_case.py](examples/workflow_switch_case.py) | A workflow with switch-case routing: a Classifier agent uses structured outputs to categorize a message and route to a specialized handler. |
215+
| [workflow_converge.py](examples/workflow_converge.py) | A branch-and-converge workflow: Reviewer routes to Publisher or Editor, then converges before final summary output. |
197216
| [agent_otel_aspire.py](examples/agent_otel_aspire.py) | An agent with OpenTelemetry tracing, metrics, and structured logs exported to the [Aspire Dashboard](https://aspire.dev/dashboard/standalone/). |
198217
| [agent_otel_appinsights.py](examples/agent_otel_appinsights.py) | An agent with OpenTelemetry tracing, metrics, and structured logs exported to [Azure Application Insights](https://learn.microsoft.com/azure/azure-monitor/app/app-insights-overview). Requires Azure provisioning via `azd provision`. |
218+
| [agent_evaluation_generate.py](examples/agent_evaluation_generate.py) | Generate synthetic evaluation data for the travel planner agent. |
199219
| [agent_evaluation.py](examples/agent_evaluation.py) | Evaluate a travel planner agent using [Azure AI Evaluation](https://learn.microsoft.com/azure/ai-foundry/concepts/evaluation-evaluators/agent-evaluators) agent evaluators (IntentResolution, ToolCallAccuracy, TaskAdherence, ResponseCompleteness). Optionally set `AZURE_AI_PROJECT` in `.env` to log results to [Azure AI Foundry](https://learn.microsoft.com/azure/ai-foundry/how-to/develop/agent-evaluate-sdk). |
220+
| [agent_evaluation_batch.py](examples/agent_evaluation_batch.py) | Batch evaluation of agent responses using Azure AI Evaluation's `evaluate()` function. |
200221
| [agent_redteam.py](examples/agent_redteam.py) | Red-team a financial advisor agent using [Azure AI Evaluation](https://learn.microsoft.com/azure/ai-foundry/how-to/develop/red-teaming-agent) to test resilience against adversarial attacks across risk categories (Violence, HateUnfairness, Sexual, SelfHarm). Requires `AZURE_AI_PROJECT` in `.env`. |
201222
202223
## Using the Aspire Dashboard for telemetry

examples/sample_document.pdf

1.11 MB
Binary file not shown.

examples/spanish/README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,17 +181,38 @@ Puedes ejecutar los ejemplos en este repositorio ejecutando los scripts en el di
181181
| [agent_tool.py](agent_tool.py) | Un agente con una sola herramienta de clima. |
182182
| [agent_tools.py](agent_tools.py) | Un agente planificador de fin de semana con múltiples herramientas. |
183183
| [agent_session.py](agent_session.py) | Sesiones en memoria para conversaciones multi-turno con memoria entre mensajes. |
184+
| [agent_history_sqlite.py](agent_history_sqlite.py) | Historial de chat persistente con un proveedor de historial SQLite personalizado para persistencia local en archivo. |
184185
| [agent_history_redis.py](agent_history_redis.py) | Historial de chat persistente con Redis para conversación que sobrevive reinicios. |
186+
| [agent_memory_redis.py](agent_memory_redis.py) | Memoria de largo plazo con RedisContextProvider, guardando y recuperando contexto conversacional desde Redis. |
187+
| [agent_memory_mem0.py](agent_memory_mem0.py) | Memoria de largo plazo con Mem0 OSS, extrayendo y recordando hechos del usuario entre sesiones. |
185188
| [agent_supervisor.py](agent_supervisor.py) | Un supervisor que orquesta subagentes de actividades y recetas. |
189+
| [agent_with_subagent.py](agent_with_subagent.py) | Aislamiento de contexto con subagentes para mantener los prompts enfocados en herramientas relevantes. |
190+
| [agent_without_subagent.py](agent_without_subagent.py) | Ejemplo de inflado de contexto cuando un solo agente carga todos los esquemas de herramientas en un mismo prompt. |
191+
| [agent_summarization.py](agent_summarization.py) | Compactación de contexto mediante middleware de resumen para reducir el uso de tokens en conversaciones largas. |
186192
| [agent_middleware.py](agent_middleware.py) | Middleware de agente, chat y funciones para logging, timing y bloqueo. |
193+
| [agent_knowledge_aisearch.py](agent_knowledge_aisearch.py) | Recuperación de conocimiento (RAG) usando Azure AI Search con AgentFrameworkAzureAISearchRAG. |
187194
| [agent_knowledge_sqlite.py](agent_knowledge_sqlite.py) | Recuperación de conocimiento (RAG) usando un proveedor de contexto personalizado con SQLite FTS5. |
195+
| [agent_knowledge_pg.py](agent_knowledge_pg.py) | Recuperación de conocimiento (RAG) con PostgreSQL y búsqueda híbrida (pgvector + texto completo) usando Reciprocal Rank Fusion. |
196+
| [agent_knowledge_pg_rewrite.py](agent_knowledge_pg_rewrite.py) | Recuperación de conocimiento con reescritura de consultas para conversaciones multi-turno sobre PostgreSQL. |
188197
| [agent_knowledge_postgres.py](agent_knowledge_postgres.py) | Recuperación de conocimiento (RAG) con búsqueda híbrida en PostgreSQL (pgvector + texto completo) usando Reciprocal Rank Fusion. |
189198
| [agent_mcp_remote.py](agent_mcp_remote.py) | Un agente usando un servidor MCP remoto (Microsoft Learn) para búsqueda de documentación. |
190199
| [agent_mcp_local.py](agent_mcp_local.py) | Un agente conectado a un servidor MCP local (p. ej. para registro de gastos). |
191200
| [openai_tool_calling.py](openai_tool_calling.py) | Llamadas a herramientas con el SDK de OpenAI de bajo nivel, mostrando despacho manual de herramientas. |
201+
| [workflow_rag_ingest.py](workflow_rag_ingest.py) | Un pipeline de ingesta para RAG con ejecutores Python puros: descarga un documento con markitdown, lo divide en fragmentos y genera embeddings con un modelo de OpenAI. |
202+
| [workflow_agents.py](workflow_agents.py) | Un workflow con agentes de IA como ejecutores: un Escritor redacta contenido y un Revisor da retroalimentación. |
203+
| [workflow_agents_sequential.py](workflow_agents_sequential.py) | Una orquestación secuencial usando `SequentialBuilder`: Escritor y Revisor se ejecutan en orden compartiendo todo el historial de la conversación. |
204+
| [workflow_agents_streaming.py](workflow_agents_streaming.py) | El mismo workflow Escritor → Revisor usando `run(stream=True)` para observar los eventos `executor_invoked`, `executor_completed` y `output` en tiempo real. |
205+
| [workflow_conditional.py](workflow_conditional.py) | Un workflow mínimo con aristas condicionales: el Revisor enruta al Publicador (aprobado) o al Editor (necesita revisión) según una señal de texto. |
206+
| [workflow_conditional_structured.py](workflow_conditional_structured.py) | El mismo patrón de enrutamiento con aristas condicionales, pero usando salida estructurada del revisor (`response_format`) para decisiones tipadas en vez de matching por cadena. |
207+
| [workflow_conditional_state.py](workflow_conditional_state.py) | Un workflow condicional con estado y bucle iterativo: guarda el último borrador en el estado del workflow y publica desde ese estado tras la aprobación. |
208+
| [workflow_conditional_state_isolated.py](workflow_conditional_state_isolated.py) | El workflow condicional con estado usando una fábrica `create_workflow(...)` para crear agentes/workflow nuevos por tarea y así aislar estado e hilos de agente. |
209+
| [workflow_switch_case.py](workflow_switch_case.py) | Un workflow con enrutamiento switch-case: un agente Clasificador usa salidas estructuradas para categorizar un mensaje y enrutarlo al manejador especializado. |
210+
| [workflow_converge.py](workflow_converge.py) | Un workflow con rama y convergencia: Revisor enruta a Publicador o Editor y luego converge antes del resumen final. |
192211
| [agent_otel_aspire.py](agent_otel_aspire.py) | Un agente con trazas, métricas y logs estructurados de OpenTelemetry exportados al [Aspire Dashboard](https://aspire.dev/dashboard/standalone/). |
193212
| [agent_otel_appinsights.py](agent_otel_appinsights.py) | Un agente con trazas, métricas y logs estructurados de OpenTelemetry exportados a [Azure Application Insights](https://learn.microsoft.com/azure/azure-monitor/app/app-insights-overview). Requiere aprovisionamiento de Azure con `azd provision`. |
213+
| [agent_evaluation_generate.py](agent_evaluation_generate.py) | Genera datos sintéticos de evaluación para el agente planificador de viajes. |
194214
| [agent_evaluation.py](agent_evaluation.py) | Evalúa un agente planificador de viajes usando evaluadores de [Azure AI Evaluation](https://learn.microsoft.com/azure/ai-foundry/concepts/evaluation-evaluators/agent-evaluators) (IntentResolution, ToolCallAccuracy, TaskAdherence, ResponseCompleteness). Opcionalmente configura `AZURE_AI_PROJECT` en `.env` para registrar resultados en [Azure AI Foundry](https://learn.microsoft.com/azure/ai-foundry/how-to/develop/agent-evaluate-sdk). |
215+
| [agent_evaluation_batch.py](agent_evaluation_batch.py) | Evaluación por lotes de respuestas de agentes con la función `evaluate()` de Azure AI Evaluation. |
195216
| [agent_redteam.py](agent_redteam.py) | Prueba de red team a un agente asesor financiero usando [Azure AI Evaluation](https://learn.microsoft.com/azure/ai-foundry/how-to/develop/red-teaming-agent) para evaluar su resiliencia ante ataques adversariales en categorías de riesgo (Violence, HateUnfairness, Sexual, SelfHarm). Requiere `AZURE_AI_PROJECT` en `.env`. |
196217
197218
## Usar el Aspire Dashboard para telemetría
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
"""Workflow Escritor → Revisor usando agentes de IA como ejecutores.
2+
3+
Demuestra: Agent como ejecutor de WorkflowBuilder, aristas directas
4+
y recopilación de salida con workflow.run() + get_outputs().
5+
6+
Este ejemplo usa el mismo patrón WorkflowBuilder + add_edge que
7+
workflow_rag_ingest.py, pero con agentes de IA en lugar de funciones Python.
8+
9+
Ejecutar:
10+
uv run examples/spanish/workflow_agents.py
11+
uv run examples/spanish/workflow_agents.py --devui (abre DevUI en http://localhost:8092)
12+
"""
13+
14+
import asyncio
15+
import os
16+
import sys
17+
18+
from agent_framework import Agent, WorkflowBuilder
19+
from agent_framework.openai import OpenAIChatClient
20+
from azure.identity.aio import DefaultAzureCredential, get_bearer_token_provider
21+
from dotenv import load_dotenv
22+
23+
load_dotenv(override=True)
24+
API_HOST = os.getenv("API_HOST", "github")
25+
26+
# Configura el cliente de chat según el proveedor de API
27+
async_credential = None
28+
if API_HOST == "azure":
29+
async_credential = DefaultAzureCredential()
30+
token_provider = get_bearer_token_provider(async_credential, "https://cognitiveservices.azure.com/.default")
31+
client = OpenAIChatClient(
32+
base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT']}/openai/v1/",
33+
api_key=token_provider,
34+
model_id=os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT"],
35+
)
36+
elif API_HOST == "github":
37+
client = OpenAIChatClient(
38+
base_url="https://models.github.ai/inference",
39+
api_key=os.environ["GITHUB_TOKEN"],
40+
model_id=os.getenv("GITHUB_MODEL", "openai/gpt-4o-mini"),
41+
)
42+
else:
43+
client = OpenAIChatClient(
44+
api_key=os.environ["OPENAI_API_KEY"], model_id=os.environ.get("OPENAI_MODEL", "gpt-4o-mini")
45+
)
46+
47+
# Crea los agentes de IA — se pasan directamente como ejecutores al WorkflowBuilder,
48+
# igual que las subclases de Executor en workflow_rag_ingest.py.
49+
writer = Agent(
50+
client=client,
51+
name="Escritor",
52+
instructions=(
53+
"Eres un escritor de contenido conciso. "
54+
"Escribe un artículo corto (2-3 párrafos) claro y atractivo sobre el tema del usuario. "
55+
"Prioriza la precisión y la legibilidad."
56+
),
57+
)
58+
59+
reviewer = Agent(
60+
client=client,
61+
name="Revisor",
62+
instructions=(
63+
"Eres un revisor de contenido reflexivo. "
64+
"Lee el borrador del escritor y ofrece retroalimentación específica y constructiva. "
65+
"Comenta sobre la claridad, la precisión y la estructura. Mantén tu revisión concisa."
66+
),
67+
)
68+
69+
# Construye el workflow: Escritor → Revisor
70+
# El mismo patrón WorkflowBuilder.add_edge funciona tanto para ejecutores Python
71+
# como para agentes de IA — la estructura del grafo es idéntica.
72+
workflow = WorkflowBuilder(start_executor=writer).add_edge(writer, reviewer).build()
73+
74+
75+
async def main():
76+
prompt = "Escribe una publicación de LinkedIn de 2 frases: \"Por qué tu piloto de IA se ve bien, pero falla en producción.\""
77+
print(f"Prompt: {prompt}\n")
78+
events = await workflow.run(prompt)
79+
print(events.get_outputs())
80+
81+
if async_credential:
82+
await async_credential.close()
83+
84+
85+
if __name__ == "__main__":
86+
if "--devui" in sys.argv:
87+
from agent_framework.devui import serve
88+
89+
serve(entities=[workflow], port=8092, auto_open=True)
90+
else:
91+
asyncio.run(main())

0 commit comments

Comments
 (0)