diff --git a/examples/tutorials/00_sync/000_hello_acp/README.md b/examples/tutorials/00_sync/000_hello_acp/README.md index d2d1eb6c..ac7f1c63 100644 --- a/examples/tutorials/00_sync/000_hello_acp/README.md +++ b/examples/tutorials/00_sync/000_hello_acp/README.md @@ -1,7 +1,43 @@ # [Sync] Hello ACP -This is a simple AgentEx agent that just says hello and acknowledges the user's message to show which ACP methods need to be implemented for the sync ACP type. +The simplest agent type: synchronous request/response pattern with a single `@acp.on_message_send` handler. Best for stateless operations that complete immediately. -## Official Documentation +## What You'll Learn +- Building a basic synchronous agent +- The `@acp.on_message_send` handler pattern +- When to use sync vs agentic agents -[000 Hello ACP](https://dev.agentex.scale.com/docs/tutorials/sync/000_hello_acp) +## Prerequisites +- Development environment set up (see [main repo README](https://github.com/scaleapi/scale-agentex)) +- Backend services running: `make dev` from repository root + +## Quick Start + +```bash +cd examples/tutorials/00_sync/000_hello_acp +uv run agentex agents run --manifest manifest.yaml +``` + +## Key Code + +```python +@acp.on_message_send +async def handle_message_send(params: SendMessageParams): + return TextContent( + author="agent", + content=f"Echo: {params.content.content}" + ) +``` + +That's it - one handler, immediate response. No task creation, no state management. + +## When to Use +- Simple chatbots with no memory requirements +- Quick Q&A or information lookup agents +- Prototyping and testing agent responses +- Operations that complete in under a second + +## Why This Matters +Sync agents are the simplest way to get started with AgentEx. They're perfect for learning the basics and building stateless agents. Once you need conversation memory or task tracking, you'll graduate to agentic agents. + +**Next:** [010_multiturn](../010_multiturn/) - Add conversation memory to your agent diff --git a/examples/tutorials/00_sync/010_multiturn/README.md b/examples/tutorials/00_sync/010_multiturn/README.md index e095927d..92abab5f 100644 --- a/examples/tutorials/00_sync/010_multiturn/README.md +++ b/examples/tutorials/00_sync/010_multiturn/README.md @@ -1,7 +1,54 @@ # [Sync] Multiturn -This tutorial demonstrates how to handle multiturn conversations in AgentEx agents using the Agent 2 Client Protocol (ACP). +Handle multi-turn conversations in synchronous agents by manually maintaining conversation history and context between messages. -## Official Documentation +## What You'll Learn +- How to handle conversation history in sync agents +- Building context from previous messages +- The limitations of stateless multiturn patterns -[010 Multiturn](https://dev.agentex.scale.com/docs/tutorials/sync/010_multiturn) \ No newline at end of file +## Prerequisites +- Development environment set up (see [main repo README](https://github.com/scaleapi/scale-agentex)) +- Backend services running: `make dev` from repository root +- Understanding of basic sync agents (see [000_hello_acp](../000_hello_acp/)) + +## Quick Start + +```bash +cd examples/tutorials/00_sync/010_multiturn +uv run agentex agents run --manifest manifest.yaml +``` + +## Key Pattern + +Sync agents are stateless by default. To handle multi-turn conversations, you need to: +1. Accept conversation history in the request +2. Maintain context across messages +3. Return responses that build on previous exchanges + +```python +@acp.on_message_send +async def handle_message_send(params: SendMessageParams): + # Accept conversation history from client + history = params.conversation_history + + # Build context from history + context = build_context(history) + + # Generate response considering full context + response = generate_response(params.content, context) + + return TextContent(author="agent", content=response) +``` + +The handler accepts history, builds context, and returns responses that reference previous exchanges. + +## When to Use +- Simple chatbots that need conversation memory +- When client can maintain and send conversation history +- Quick prototypes before building full agentic agents + +## Why This Matters +While sync agents can handle conversations, you're responsible for managing state on the client side. This becomes complex quickly. For production conversational agents, consider agentic agents ([10_agentic/00_base/010_multiturn](../../10_agentic/00_base/010_multiturn/)) where the platform manages state automatically. + +**Next:** [020_streaming](../020_streaming/) - Stream responses in real-time diff --git a/examples/tutorials/00_sync/020_streaming/README.md b/examples/tutorials/00_sync/020_streaming/README.md index b936628f..0204bf37 100644 --- a/examples/tutorials/00_sync/020_streaming/README.md +++ b/examples/tutorials/00_sync/020_streaming/README.md @@ -1,9 +1,45 @@ # [Sync] Streaming -This tutorial demonstrates how to implement streaming responses in AgentEx agents using the Agent 2 Client Protocol (ACP). +Stream responses progressively using async generators instead of returning a single message. Enables showing partial results as they're generated. -## Official Documentation +## What You'll Learn +- How to stream responses using async generators +- The `yield` pattern for progressive updates +- When streaming improves user experience -[020 Streaming](https://dev.agentex.scale.com/docs/tutorials/sync/020_streaming) +## Prerequisites +- Development environment set up (see [main repo README](https://github.com/scaleapi/scale-agentex)) +- Backend services running: `make dev` from repository root +- Understanding of basic sync agents (see [000_hello_acp](../000_hello_acp/)) +## Quick Start +```bash +cd examples/tutorials/00_sync/020_streaming +uv run agentex agents run --manifest manifest.yaml +``` + +## Key Code + +```python +@acp.on_message_send +async def handle_message_send(params: SendMessageParams): + async def stream_response(): + for chunk in response_chunks: + yield TaskMessageUpdate(content=TextContent(...)) + + return stream_response() +``` + +Return an async generator instead of a single response - each `yield` sends an update to the client. + +## When to Use +- Streaming LLM responses (OpenAI, Anthropic, etc.) +- Large data processing with progress updates +- Any operation that takes >1 second to complete +- Improving perceived responsiveness + +## Why This Matters +Streaming dramatically improves user experience for longer operations. Instead of waiting 10 seconds for a complete response, users see results immediately as they're generated. This is essential for modern AI agents. + +**Next:** Ready for task management? → [10_agentic/00_base/000_hello_acp](../../10_agentic/00_base/000_hello_acp/) diff --git a/examples/tutorials/10_agentic/00_base/000_hello_acp/README.md b/examples/tutorials/10_agentic/00_base/000_hello_acp/README.md index 36008586..59bf95d6 100644 --- a/examples/tutorials/10_agentic/00_base/000_hello_acp/README.md +++ b/examples/tutorials/10_agentic/00_base/000_hello_acp/README.md @@ -1,7 +1,49 @@ # [Agentic] Hello ACP -This tutorial demonstrates how to implement the base agentic ACP type in AgentEx agents. +Agentic agents use three handlers for async task management: `on_task_create`, `on_task_event_send`, and `on_task_cancel`. Unlike sync agents, tasks persist and can receive multiple events over time. -## Official Documentation +## What You'll Learn +- The three-handler pattern for agentic agents +- How tasks differ from sync messages +- When to use agentic vs sync agents -[000 Hello Base Agentic](https://dev.agentex.scale.com/docs/tutorials/agentic/base/hello_acp/) \ No newline at end of file +## Prerequisites +- Development environment set up (see [main repo README](https://github.com/scaleapi/scale-agentex)) +- Backend services running: `make dev` from repository root +- Understanding of sync agents (see [00_sync/000_hello_acp](../../../00_sync/000_hello_acp/)) + +## Quick Start + +```bash +cd examples/tutorials/10_agentic/00_base/000_hello_acp +uv run agentex agents run --manifest manifest.yaml +``` + +## Key Pattern + +```python +@acp.on_task_create +async def handle_task_create(params: CreateTaskParams): + # Initialize task state, send welcome message + +@acp.on_task_event_send +async def handle_event_send(params: SendEventParams): + # Handle each message/event in the task + +@acp.on_task_cancel +async def handle_task_cancel(params: CancelTaskParams): + # Cleanup when task is cancelled +``` + +Three handlers instead of one, giving you full control over task lifecycle. Tasks can receive multiple events and maintain state across them. + +## When to Use +- Conversational agents that need memory +- Operations that require task tracking +- Agents that need lifecycle management (initialization, cleanup) +- Building towards production systems + +## Why This Matters +The task-based model is the foundation of production agents. Unlike sync agents where each message is independent, agentic agents maintain persistent tasks that can receive multiple events, store state, and have full lifecycle management. This is the stepping stone to Temporal-based agents. + +**Next:** [010_multiturn](../010_multiturn/) - Add conversation memory diff --git a/examples/tutorials/10_agentic/00_base/010_multiturn/README.md b/examples/tutorials/10_agentic/00_base/010_multiturn/README.md index 40eb8d84..6c7b3a4f 100644 --- a/examples/tutorials/10_agentic/00_base/010_multiturn/README.md +++ b/examples/tutorials/10_agentic/00_base/010_multiturn/README.md @@ -1,7 +1,61 @@ # [Agentic] Multiturn -This tutorial demonstrates how to handle multiturn conversations in AgentEx agents using the agentic ACP type. +Handle multi-turn conversations in agentic agents with task-based state management. Each task maintains its own conversation history automatically. -## Official Documentation +## What You'll Learn +- How tasks maintain conversation state across multiple exchanges +- Difference between sync and agentic multiturn patterns +- Building stateful conversational agents with minimal code -[010 Multiturn Base Agentic](https://dev.agentex.scale.com/docs/tutorials/agentic/base/multiturn/) +## Prerequisites +- Development environment set up (see [main repo README](https://github.com/scaleapi/scale-agentex)) +- Backend services running: `make dev` from repository root +- Understanding of basic agentic agents (see [000_hello_acp](../000_hello_acp/)) + +## Quick Start + +```bash +cd examples/tutorials/10_agentic/00_base/010_multiturn +uv run agentex agents run --manifest manifest.yaml +``` + +## Key Pattern + +Unlike sync agents where you manually track conversation history, agentic agents automatically maintain state within each task: + +```python +@app.on_task_event_send() +async def on_task_event_send(event_send: TaskEventSendInput): + # The task's messages list automatically includes all previous exchanges + messages = event_send.task.messages + + # No need to manually pass history - it's already there! + response = await openai_client.chat.completions.create( + model="gpt-4o-mini", + messages=messages + ) + + return {"content": response.choices[0].message.content} +``` + +## Try It + +1. Start the agent with the command above +2. Open the web UI or use the notebook to create a task +3. Send multiple messages in the same task: + - "What's 25 + 17?" + - "What was that number again?" + - "Multiply it by 2" +4. Notice the agent remembers context from previous exchanges + +## When to Use +- Conversational agents that need memory across exchanges +- Chat interfaces where users ask follow-up questions +- Agents that build context over time within a session + +## Why This Matters +Task-based state management eliminates the complexity of manually tracking conversation history. The AgentEx platform handles state persistence automatically, making it easier to build stateful agents without custom session management code. + +**Comparison:** In the sync version ([00_sync/010_multiturn](../../../00_sync/010_multiturn/)), you manually manage conversation history. Here, the task object does it for you. + +**Next:** [020_streaming](../020_streaming/) - Add real-time streaming responses diff --git a/examples/tutorials/10_agentic/00_base/020_streaming/README.md b/examples/tutorials/10_agentic/00_base/020_streaming/README.md index bbd1d90b..43026b42 100644 --- a/examples/tutorials/10_agentic/00_base/020_streaming/README.md +++ b/examples/tutorials/10_agentic/00_base/020_streaming/README.md @@ -1,7 +1,47 @@ # [Agentic] Streaming -This tutorial demonstrates how to implement streaming responses in AgentEx agents using the agentic ACP type. +Stream responses in agentic agents using `adk.messages.create()` to send progressive updates. More flexible than sync streaming since you can send multiple messages at any time. -## Official Documentation +## What You'll Learn +- How to stream with explicit message creation +- Difference between sync and agentic streaming patterns +- When to send multiple messages vs single streamed response -[020 Streaming Base Agentic](https://dev.agentex.scale.com/docs/tutorials/agentic/base/streaming/) \ No newline at end of file +## Prerequisites +- Development environment set up (see [main repo README](https://github.com/scaleapi/scale-agentex)) +- Backend services running: `make dev` from repository root +- Understanding of agentic basics (see [000_hello_acp](../000_hello_acp/)) + +## Quick Start + +```bash +cd examples/tutorials/10_agentic/00_base/020_streaming +uv run agentex agents run --manifest manifest.yaml +``` + +## Key Pattern + +```python +@acp.on_task_event_send +async def handle_event_send(params: SendEventParams): + # Send first message + await adk.messages.create(task_id=task_id, content=...) + + # Do work... + + # Send second message + await adk.messages.create(task_id=task_id, content=...) +``` + +Unlike sync streaming (which uses async generators), agentic streaming uses explicit message creation calls, giving you more control over when and what to send. + +## When to Use +- Multi-step processes with intermediate results +- Long-running operations with progress updates +- Agents that need to send messages at arbitrary times +- More complex streaming patterns than simple LLM responses + +## Why This Matters +Agentic streaming is more powerful than sync streaming. You can send messages at any time, from anywhere in your code, and even from background tasks. This flexibility is essential for complex agents with multiple concurrent operations. + +**Next:** [030_tracing](../030_tracing/) - Add observability to your agents diff --git a/examples/tutorials/10_agentic/00_base/030_tracing/README.md b/examples/tutorials/10_agentic/00_base/030_tracing/README.md index ea41a8f8..8a67c5dc 100644 --- a/examples/tutorials/10_agentic/00_base/030_tracing/README.md +++ b/examples/tutorials/10_agentic/00_base/030_tracing/README.md @@ -1,7 +1,53 @@ # [Agentic] Tracing -This tutorial demonstrates how to implement hierarchical and custom tracing in AgentEx agents using the agentic ACP type. +Add observability to your agents with spans and traces using `adk.tracing.start_span()`. Track execution flow, measure performance, and debug complex agent behaviors. -## Official Documentation +## What You'll Learn +- How to instrument agents with tracing +- Creating hierarchical spans to track operations +- Viewing traces in Scale Groundplane +- Performance debugging with observability -[030 Tracing Base Agentic](https://dev.agentex.scale.com/docs/tutorials/agentic/base/tracing/) \ No newline at end of file +## Prerequisites +- Development environment set up (see [main repo README](https://github.com/scaleapi/scale-agentex)) +- Backend services running: `make dev` from repository root +- Understanding of agentic agents (see [000_hello_acp](../000_hello_acp/)) + +## Quick Start + +```bash +cd examples/tutorials/10_agentic/00_base/030_tracing +uv run agentex agents run --manifest manifest.yaml +``` + +## Key Pattern + +```python +# Start a span to track an operation +span = await adk.tracing.start_span( + trace_id=task.id, + name="LLM Call", + input={"prompt": prompt} +) + +# Do work... + +# End span with output +await adk.tracing.end_span( + span_id=span.id, + output={"response": response} +) +``` + +Spans create a hierarchical view of agent execution, making it easy to see which operations take time and where errors occur. + +## When to Use +- Debugging complex agent behaviors +- Performance optimization and bottleneck identification +- Production monitoring and observability +- Understanding execution flow in multi-step agents + +## Why This Matters +Without tracing, debugging agents is like flying blind. Tracing gives you visibility into what your agent is doing, how long operations take, and where failures occur. It's essential for production agents and invaluable during development. + +**Next:** [040_other_sdks](../040_other_sdks/) - Integrate any SDK or framework diff --git a/examples/tutorials/10_agentic/00_base/040_other_sdks/README.md b/examples/tutorials/10_agentic/00_base/040_other_sdks/README.md index 8be83e82..7234f3d6 100644 --- a/examples/tutorials/10_agentic/00_base/040_other_sdks/README.md +++ b/examples/tutorials/10_agentic/00_base/040_other_sdks/README.md @@ -1,7 +1,45 @@ # [Agentic] Other SDKs -This tutorial demonstrates how to use other SDKs in AgentEx agents to show the flexibility that agents are just code. +Agents are just Python code - integrate any SDK you want (OpenAI, Anthropic, LangChain, LlamaIndex, custom libraries, etc.). AgentEx doesn't lock you into a specific framework. -## Official Documentation +## What You'll Learn +- How to integrate OpenAI, Anthropic, or any SDK +- What AgentEx provides vs what you bring +- Framework-agnostic agent development +- Building agents with your preferred tools -[040 Other SDKs Base Agentic](https://dev.agentex.scale.com/docs/tutorials/agentic/base/other_sdks/) \ No newline at end of file +## Prerequisites +- Development environment set up (see [main repo README](https://github.com/scaleapi/scale-agentex)) +- Backend services running: `make dev` from repository root +- Understanding of agentic agents (see [000_hello_acp](../000_hello_acp/)) + +## Quick Start + +```bash +cd examples/tutorials/10_agentic/00_base/040_other_sdks +uv run agentex agents run --manifest manifest.yaml +``` + +## Key Insight + +AgentEx provides: +- ACP protocol implementation (task management, message handling) +- Deployment infrastructure +- Monitoring and observability + +You provide: +- Agent logic using whatever SDK/library you want +- Tools and capabilities specific to your use case + +Mix and match OpenAI, Anthropic, LangChain, or roll your own - it's all just Python. + +## When to Use +- You have an existing agent codebase to migrate +- Your team prefers specific SDKs or frameworks +- You need features from multiple providers +- You want full control over your agent logic + +## Why This Matters +AgentEx is infrastructure, not a framework. We handle deployment, task management, and protocol implementation - you handle the agent logic with whatever tools you prefer. This keeps you flexible and avoids vendor lock-in. + +**Next:** [080_batch_events](../080_batch_events/) - See when you need Temporal diff --git a/examples/tutorials/10_agentic/00_base/080_batch_events/README.md b/examples/tutorials/10_agentic/00_base/080_batch_events/README.md index bddd3ed6..7a2efce3 100644 --- a/examples/tutorials/10_agentic/00_base/080_batch_events/README.md +++ b/examples/tutorials/10_agentic/00_base/080_batch_events/README.md @@ -1,7 +1,46 @@ # [Agentic] Batch Events -This tutorial demonstrates batch event processing and the limitations of the base agentic ACP protocol. +Demonstrates limitations of the base agentic protocol with concurrent event processing. When multiple events arrive rapidly, base agentic agents handle them sequentially, which can cause issues. -## Official Documentation +## What You'll Learn +- Limitations of non-Temporal agentic agents +- Race conditions and ordering issues in concurrent scenarios +- When you need workflow orchestration +- Why this motivates Temporal adoption -[080 Batch Events Base Agentic](https://dev.agentex.scale.com/docs/tutorials/agentic/base/batch_events/) +## Prerequisites +- Development environment set up (see [main repo README](https://github.com/scaleapi/scale-agentex)) +- Backend services running: `make dev` from repository root +- Understanding of agentic patterns (see previous tutorials) + +## Quick Start + +```bash +cd examples/tutorials/10_agentic/00_base/080_batch_events +uv run agentex agents run --manifest manifest.yaml +``` + +## Why This Matters + +This tutorial shows **when you need Temporal**. If your agent needs to: +- Handle events that might arrive out of order +- Process multiple events in parallel safely +- Maintain consistent state under concurrent load + +Then you should use Temporal workflows (see tutorials 10_agentic/10_temporal/) which provide: +- Deterministic event ordering +- Safe concurrent processing +- Guaranteed state consistency + +This is the "breaking point" tutorial that motivates moving to Temporal for production agents. + +## When to Use (This Pattern) +This tutorial shows what NOT to use for production. Use base agentic agents only when: +- Events are infrequent (< 1 per second) +- Order doesn't matter +- State consistency isn't critical + +## Why This Matters +Every production agent eventually hits concurrency issues. This tutorial shows you those limits early, so you know when to graduate to Temporal. Better to learn this lesson in a tutorial than in production! + +**Next:** Ready for production? → [../10_temporal/000_hello_acp](../../10_temporal/000_hello_acp/) or explore [090_multi_agent_non_temporal](../090_multi_agent_non_temporal/) for complex non-Temporal coordination diff --git a/examples/tutorials/10_agentic/00_base/090_multi_agent_non_temporal/README.md b/examples/tutorials/10_agentic/00_base/090_multi_agent_non_temporal/README.md index 2cba9e17..476b75ee 100644 --- a/examples/tutorials/10_agentic/00_base/090_multi_agent_non_temporal/README.md +++ b/examples/tutorials/10_agentic/00_base/090_multi_agent_non_temporal/README.md @@ -45,9 +45,11 @@ The system uses a shared build configuration with type-safe interfaces: ## 🚀 Quick Start ### Prerequisites -- Python 3.12+ -- uv package manager +- Development environment set up (see [main repo README](https://github.com/scaleapi/scale-agentex)) +- Backend services running: `make dev` from repository root +- Python 3.12+ and uv package manager - OpenAI API key (set `OPENAI_API_KEY` or create `.env` file) +- Understanding of agentic patterns (see previous tutorials) ### Running the System @@ -195,3 +197,14 @@ This tutorial demonstrates: - **AgentEx CLI usage** for development and deployment - **Inter-agent communication patterns** with proper error handling - **Scalable agent architecture** with clear separation of concerns + +## When to Use +- Complex workflows requiring multiple specialized agents +- Content pipelines with review/approval steps +- Systems where each stage needs different capabilities +- When you want agent separation without Temporal (though Temporal is recommended for production) + +## Why This Matters +This shows how far you can go with non-Temporal multi-agent systems. However, note the limitations: manual state management, potential race conditions, and no built-in durability. For production multi-agent systems, consider Temporal ([../10_temporal/](../../10_temporal/)) which provides workflow orchestration, durability, and state management out of the box. + +**Next:** Ready for production workflows? → [../../10_temporal/000_hello_acp](../../10_temporal/000_hello_acp/) diff --git a/examples/tutorials/10_agentic/10_temporal/000_hello_acp/README.md b/examples/tutorials/10_agentic/10_temporal/000_hello_acp/README.md index 3cb435ec..6a5431f5 100644 --- a/examples/tutorials/10_agentic/10_temporal/000_hello_acp/README.md +++ b/examples/tutorials/10_agentic/10_temporal/000_hello_acp/README.md @@ -1,7 +1,55 @@ -# [Agentic] Hello ACP with Temporal +# [Temporal] Hello ACP -This tutorial demonstrates how to implement the agentic ACP type with Temporal workflows in AgentEx agents. +Temporal workflows make agents durable - they survive restarts and can run indefinitely without consuming resources while idle. Instead of handlers, you define a workflow class with `@workflow.run` and `@workflow.signal` methods. -## Official Documentation +## What You'll Learn +- Building durable agents with Temporal workflows +- The workflow and signal pattern +- How workflows survive failures and resume automatically +- When to use Temporal vs base agentic agents -[000 Hello Temporal Agentic](https://dev.agentex.scale.com/docs/tutorials/agentic/temporal/hello_acp/) \ No newline at end of file +## Prerequisites +- Development environment set up (see [main repo README](https://github.com/scaleapi/scale-agentex)) +- Backend services running: `make dev` from repository root (includes Temporal) +- Temporal UI available at http://localhost:8233 +- Understanding of base agentic agents (see [../../00_base/080_batch_events](../../00_base/080_batch_events/) to understand why Temporal) + +## Quick Start + +```bash +cd examples/tutorials/10_agentic/10_temporal/000_hello_acp +uv run agentex agents run --manifest manifest.yaml +``` + +**Monitor:** Check Temporal UI at http://localhost:8233 to see your durable workflow running. + +## Key Pattern + +```python +@workflow.defn(name="my-workflow") +class MyWorkflow(BaseWorkflow): + @workflow.run + async def on_task_create(self, params: CreateTaskParams): + # Wait indefinitely for events - workflow stays alive + await workflow.wait_condition(lambda: self._complete) + + @workflow.signal(name=SignalName.RECEIVE_EVENT) + async def on_task_event_send(self, params: SendEventParams): + # Handle events as signals to the workflow +``` + +## When to Use +- Production agents that need guaranteed execution +- Long-running tasks (hours, days, weeks, or longer) +- Operations that must survive system failures +- Agents with concurrent event handling requirements +- When you need durability and observability + +## Why This Matters +**Without Temporal:** If your worker crashes, the agent loses all state and has to start over. + +**With Temporal:** The workflow resumes exactly where it left off. If it crashes mid-conversation, Temporal brings it back up with full context intact. Can run for years if needed, only consuming resources when actively processing. + +This is the foundation for production-ready agents that handle real-world reliability requirements. + +**Next:** [010_agent_chat](../010_agent_chat/) - Build a complete conversational agent with tools diff --git a/examples/tutorials/10_agentic/10_temporal/010_agent_chat/README.md b/examples/tutorials/10_agentic/10_temporal/010_agent_chat/README.md index 3b809817..4707472c 100644 --- a/examples/tutorials/10_agentic/10_temporal/010_agent_chat/README.md +++ b/examples/tutorials/10_agentic/10_temporal/010_agent_chat/README.md @@ -1,7 +1,47 @@ -# [Agentic] Agent Chat with Temporal +# [Temporal] Agent Chat -This tutorial demonstrates how to implement streaming multiturn tool-enabled chat with tracing using Temporal workflows in AgentEx agents. +Combine streaming responses, multi-turn chat, tool calling, and tracing - all with Temporal's durability guarantees. This shows how to build a complete conversational agent that can survive failures. -## Official Documentation +## What You'll Learn +- Building a complete conversational agent with Temporal +- Combining streaming, multiturn, tools, and tracing +- How all agent capabilities work together with durability +- Production-ready conversational patterns -[010 Agent Chat Temporal Agentic](https://dev.agentex.scale.com/docs/tutorials/agentic/temporal/agent_chat/) \ No newline at end of file +## Prerequisites +- Development environment set up (see [main repo README](https://github.com/scaleapi/scale-agentex)) +- Backend services running: `make dev` from repository root +- Temporal UI available at http://localhost:8233 +- Understanding of Temporal basics (see [000_hello_acp](../000_hello_acp/)) + +## Quick Start + +```bash +cd examples/tutorials/10_agentic/10_temporal/010_agent_chat +uv run agentex agents run --manifest manifest.yaml +``` + +## Key Pattern + +- **Streaming**: Progressive response generation with `adk.messages.create()` +- **Multi-turn**: Conversation history maintained in durable workflow state +- **Tools**: Agent can call functions to perform actions +- **Tracing**: Full observability of tool calls and LLM interactions +- **Durability**: All of the above survives worker restarts + +**Monitor:** Open Temporal UI at http://localhost:8233 to see the workflow and all tool call activities. + +## Key Insight + +In base agentic agents, all this state lives in memory and is lost on crash. With Temporal, the entire conversation - history, tool calls, intermediate state - is durably persisted. The agent can pick up a conversation that paused days ago as if no time passed. + +## When to Use +- Production chatbots with tool capabilities +- Long-running customer service conversations +- Agents that need both reliability and rich features +- Any conversational agent handling real user traffic + +## Why This Matters +This is the pattern for real production agents. By combining all capabilities (streaming, tools, tracing) with Temporal's durability, you get an agent that's both feature-rich and reliable. This is what enterprise conversational AI looks like. + +**Next:** [020_state_machine](../020_state_machine/) - Add complex multi-phase workflows diff --git a/examples/tutorials/10_agentic/10_temporal/020_state_machine/README.md b/examples/tutorials/10_agentic/10_temporal/020_state_machine/README.md index b1f25661..05e0fe1c 100644 --- a/examples/tutorials/10_agentic/10_temporal/020_state_machine/README.md +++ b/examples/tutorials/10_agentic/10_temporal/020_state_machine/README.md @@ -1,7 +1,70 @@ -# [Agentic] State Machine with Temporal +# [Temporal] State Machine -This tutorial demonstrates how to use state machines to manage complex agentic workflows with Temporal in AgentEx agents. +Build complex multi-state workflows using state machines with Temporal. This tutorial shows a "deep research" agent that transitions through states: clarify query → wait for input → perform research → wait for follow-ups. -## Official Documentation +## What You'll Learn +- Building state machines with Temporal sub-workflows +- Explicit state transitions and phase management +- When to use state machines vs simple workflows +- Handling complex multi-phase agent behaviors -[020 State Machine Temporal Agentic](https://dev.agentex.scale.com/docs/tutorials/agentic/temporal/state_machine/) \ No newline at end of file +## Prerequisites +- Development environment set up (see [main repo README](https://github.com/scaleapi/scale-agentex)) +- Backend services running: `make dev` from repository root +- Temporal UI available at http://localhost:8233 +- Understanding of Temporal workflows (see [010_agent_chat](../010_agent_chat/)) + +## Quick Start + +```bash +cd examples/tutorials/10_agentic/10_temporal/020_state_machine +uv run agentex agents run --manifest manifest.yaml +``` + +**Monitor:** Open Temporal UI at http://localhost:8233 to see state transitions and sub-workflows. + +## Architecture + +The workflow uses three sub-workflows, each handling a specific state: +- `ClarifyUserQueryWorkflow` - Asks follow-up questions to understand user intent +- `WaitingForUserInputWorkflow` - Waits for user responses +- `PerformingDeepResearchWorkflow` - Executes the research with full context + +State transitions are explicit and tracked, with each sub-workflow handling its own logic. + +## Why State Machines Matter + +Complex agents often need to: +- Wait for user input at specific points +- Branch behavior based on conditions +- Orchestrate multiple steps with clear transitions +- Resume at the exact state after failures + +State machines provide this structure. Each state is a sub-workflow, and Temporal ensures transitions are durable and resumable. + +## Key Pattern + +```python +self.state_machine = DeepResearchStateMachine( + initial_state=DeepResearchState.WAITING_FOR_USER_INPUT, + states=[ + State(name=DeepResearchState.CLARIFYING, workflow=ClarifyWorkflow()), + State(name=DeepResearchState.RESEARCHING, workflow=ResearchWorkflow()), + ] +) + +await self.state_machine.transition(DeepResearchState.RESEARCHING) +``` + +This is an advanced pattern - only needed when your agent has complex, multi-phase behavior. + +## When to Use +- Multi-step processes with clear phases +- Workflows that wait for user input at specific points +- Operations with branching logic based on state +- Complex coordination patterns requiring explicit transitions + +## Why This Matters +State machines provide structure for complex agent behaviors. While simple agents can use basic workflows, complex agents benefit from explicit state management. Temporal ensures state transitions are durable and resumable, even after failures. + +**Next:** [030_custom_activities](../030_custom_activities/) - Extend workflows with custom activities diff --git a/examples/tutorials/10_agentic/10_temporal/030_custom_activities/README.md b/examples/tutorials/10_agentic/10_temporal/030_custom_activities/README.md index 0be65ef7..92aa8a03 100644 --- a/examples/tutorials/10_agentic/10_temporal/030_custom_activities/README.md +++ b/examples/tutorials/10_agentic/10_temporal/030_custom_activities/README.md @@ -1,301 +1,106 @@ -# at030-custom-activities - AgentEx Temporal Agent Template +# [Temporal] Custom Activities -This is a starter template for building asynchronous agents with the AgentEx framework and Temporal. It provides a basic implementation of the Agent 2 Client Protocol (ACP) with Temporal workflow support to help you get started quickly. +Learn how to extend Temporal workflows with custom activities for external operations like API calls, database queries, or complex computations. ## What You'll Learn +- How to define custom Temporal activities +- When to use activities vs inline workflow code +- Activity retry and timeout configuration +- Integrating external services into workflows -- **Tasks**: A task is a grouping mechanism for related messages. Think of it as a conversation thread or a session. -- **Messages**: Messages are communication objects within a task. They can contain text, data, or instructions. -- **ACP Events**: The agent responds to four main events: - - `task_received`: When a new task is created - - `task_message_received`: When a message is sent within a task - - `task_approved`: When a task is approved - - `task_canceled`: When a task is canceled -- **Temporal Workflows**: Long-running processes that can handle complex state management and async operations +## Prerequisites +- Development environment set up (see [main repo README](https://github.com/scaleapi/scale-agentex)) +- Backend services running: `make dev` from repository root +- Temporal UI available at http://localhost:8233 +- Understanding of basic Temporal workflows (see [000_hello_acp](../000_hello_acp/)) -## Running the Agent +## Quick Start -1. Run the agent locally: +**Terminal 1 - Start Worker:** ```bash -agentex agents run --manifest manifest.yaml +cd examples/tutorials/10_agentic/10_temporal/030_custom_activities +uv run python project/run_worker.py ``` -The agent will start on port 8000 and print messages whenever it receives any of the ACP events. - -## What's Inside - -This template: -- Sets up a basic ACP server with Temporal integration -- Handles each of the required ACP events -- Provides a foundation for building complex async agents -- Includes Temporal workflow and activity definitions - -## Next Steps - -For more advanced agent development, check out the AgentEx tutorials: - -- **Tutorials 00-08**: Learn about building synchronous agents with ACP -- **Tutorials 09-10**: Learn how to use Temporal to power asynchronous agents - - Tutorial 09: Basic Temporal workflow setup - - Tutorial 10: Advanced Temporal patterns and best practices - -These tutorials will help you understand: -- How to handle long-running tasks -- Implementing state machines -- Managing complex workflows -- Best practices for async agent development - -## The Manifest File - -The `manifest.yaml` file is your agent's configuration file. It defines: -- How your agent should be built and packaged -- What files are included in your agent's Docker image -- Your agent's name and description -- Local development settings (like the port your agent runs on) -- Temporal worker configuration - -This file is essential for both local development and deployment of your agent. - -## Project Structure - -``` -030_custom_activities/ -├── project/ # Your agent's code -│ ├── __init__.py -│ ├── acp.py # ACP server and event handlers -│ ├── workflow.py # Temporal workflow definitions -│ ├── activities.py # Temporal activity definitions -│ └── run_worker.py # Temporal worker setup -├── Dockerfile # Container definition -├── manifest.yaml # Deployment config -├── dev.ipynb # Development notebook for testing - -└── pyproject.toml # Dependencies (uv) - -``` - -## Development - -### 1. Customize Event Handlers -- Modify the handlers in `acp.py` to implement your agent's logic -- Add your own tools and capabilities -- Implement custom state management - -### 2. Test Your Agent with the Development Notebook -Use the included `dev.ipynb` Jupyter notebook to test your agent interactively: - +**Terminal 2 - Run Agent:** ```bash -# Start Jupyter notebook (make sure you have jupyter installed) -jupyter notebook dev.ipynb - -# Or use VS Code to open the notebook directly -code dev.ipynb -``` - -The notebook includes: -- **Setup**: Connect to your local AgentEx backend -- **Task creation**: Create a new task for the conversation -- **Event sending**: Send events to the agent and get responses -- **Async message subscription**: Subscribe to server-side events to receive agent responses -- **Rich message display**: Beautiful formatting with timestamps and author information - -The notebook automatically uses your agent name (`at030-custom-activities`) and demonstrates the agentic ACP workflow: create task → send event → subscribe to responses. - -### 3. Develop Temporal Workflows -- Edit `workflow.py` to define your agent's async workflow logic -- Modify `activities.py` to add custom activities -- Use `run_worker.py` to configure the Temporal worker - -### 4. Manage Dependencies - - -You chose **uv** for package management. Here's how to work with dependencies: - -```bash -# Add new dependencies -agentex uv add requests openai anthropic - -# Add Temporal-specific dependencies (already included) -agentex uv add temporalio - -# Install/sync dependencies -agentex uv sync - -# Run commands with uv uv run agentex agents run --manifest manifest.yaml ``` -**Benefits of uv:** -- Faster dependency resolution and installation -- Better dependency isolation -- Modern Python packaging standards - - - -### 5. Configure Credentials -- Add any required credentials to your manifest.yaml -- For local development, create a `.env` file in the project directory -- Use `load_dotenv()` only in development mode: - -```python -import os -from dotenv import load_dotenv - -if os.environ.get("ENVIRONMENT") == "development": - load_dotenv() -``` - -## Local Development - -### 1. Start the Agentex Backend -```bash -# Navigate to the backend directory -cd agentex - -# Start all services using Docker Compose -make dev - -# Optional: In a separate terminal, use lazydocker for a better UI (everything should say "healthy") -lzd -``` - -### 2. Setup Your Agent's requirements/pyproject.toml +**Terminal 3 - Test via Notebook:** ```bash -agentex uv sync [--group editable-apy] -source .venv/bin/activate - -# OR -conda create -n 030_custom_activities python=3.12 -conda activate 030_custom_activities -pip install -r requirements.txt -``` -### 3. Run Your Agent -```bash -# From this directory -export ENVIRONMENT=development && [uv run] agentex agents run --manifest manifest.yaml -``` -4. **Interact with your agent** - -Option 0: CLI (deprecated - to be replaced once a new CLI is implemented - please use the web UI for now!) -```bash -# Submit a task via CLI -agentex tasks submit --agent at030-custom-activities --task "Your task here" -``` - -Option 1: Web UI -```bash -# Start the local web interface -cd agentex-web -make dev - -# Then open http://localhost:3000 in your browser to chat with your agent +jupyter notebook dev.ipynb ``` -## Development Tips +## Key Concepts -### Environment Variables -- Set environment variables in project/.env for any required credentials -- Or configure them in the manifest.yaml under the `env` section -- The `.env` file is automatically loaded in development mode +### Activities vs Workflow Code -### Local Testing -- Use `export ENVIRONMENT=development` before running your agent -- This enables local service discovery and debugging features -- Your agent will automatically connect to locally running services +**Use activities for:** +- External API calls +- Database operations +- File I/O or network operations +- Non-deterministic operations (random, time, external state) -### Temporal-Specific Tips -- Monitor workflows in the Temporal Web UI at http://localhost:8080 -- Use the Temporal CLI for advanced workflow management -- Check workflow logs for debugging async operations +**Use workflow code for:** +- Orchestration logic +- State management +- Decision making based on activity results -### Debugging -- Check agent logs in the terminal where you ran the agent -- Use the web UI to inspect task history and responses -- Monitor backend services with `lzd` (LazyDocker) -- Use Temporal Web UI for workflow debugging +### Defining a Custom Activity -### To build the agent Docker image locally (normally not necessary): +```python +# In project/activities.py +from temporalio import activity -1. Build the agent image: -```bash -agentex agents build --manifest manifest.yaml +@activity.defn +async def call_external_api(endpoint: str, data: dict) -> dict: + """Activities can perform non-deterministic operations.""" + import httpx + async with httpx.AsyncClient() as client: + response = await client.post(endpoint, json=data) + return response.json() ``` -## Advanced Features - -### Temporal Workflows -Extend your agent with sophisticated async workflows: +### Using Activities in Workflows ```python # In project/workflow.py +from temporalio import workflow + @workflow.defn class MyWorkflow(BaseWorkflow): - async def complex_operation(self): - # Multi-step async operations - # Error handling and retries - # State management - pass -``` - -### Custom Activities -Add custom activities for external operations: - -```python -# In project/activities.py -@activity.defn -async def call_external_api(data): - # HTTP requests, database operations, etc. - pass -``` - -### Integration with External Services - -```bash -# Add service clients -agentex uv add httpx requests-oauthlib - -# Add AI/ML libraries -agentex uv add openai anthropic transformers - -# Add database clients -agentex uv add asyncpg redis + @workflow.run + async def run(self, input: dict): + # Activities are executed with retry and timeout policies + result = await workflow.execute_activity( + call_external_api, + args=["https://api.example.com", input], + start_to_close_timeout=timedelta(seconds=30), + retry_policy=RetryPolicy(maximum_attempts=3) + ) + return result ``` +## Try It -## Troubleshooting - -### Common Issues - -1. **Agent not appearing in web UI** - - Check if agent is running on port 8000 - - Verify `ENVIRONMENT=development` is set - - Check agent logs for errors - -2. **Temporal workflow issues** - - Check Temporal Web UI at http://localhost:8080 - - Verify Temporal server is running in backend services - - Check workflow logs for specific errors - -3. **Dependency issues** - - - Run `agentex uv sync` to ensure all dependencies are installed - - Verify temporalio is properly installed - +1. Modify `project/activities.py` to add a new activity +2. Update `project/workflow.py` to call your activity +3. Register the activity in `project/run_worker.py` +4. Restart the worker and test via the notebook +5. Check Temporal UI at http://localhost:8233 to see activity execution and retries -4. **Port conflicts** - - Check if another service is using port 8000 - - Use `lsof -i :8000` to find conflicting processes +## When to Use +- Integrating external services (OpenAI, databases, APIs) +- Operations that may fail and need automatic retries +- Long-running computations that should be checkpointed +- Separating business logic from orchestration -### Temporal-Specific Troubleshooting +## Why This Matters +Activities are Temporal's way of handling the real world's messiness: network failures, API rate limits, and transient errors. They provide automatic retries, timeouts, and observability for operations that would otherwise require extensive error handling code. -1. **Workflow not starting** - - Check if Temporal server is running (`docker ps`) - - Verify task queue configuration in `run_worker.py` - - Check workflow registration in the worker +--- -2. **Activity failures** - - Check activity logs in the console - - Verify activity registration - - Check for timeout issues +**For detailed setup instructions, see [TEMPLATE_GUIDE.md](./TEMPLATE_GUIDE.md)** -Happy building with Temporal! 🚀⚡ \ No newline at end of file +**Next:** [050_agent_chat_guardrails](../050_agent_chat_guardrails/) - Add safety and validation to your workflows diff --git a/examples/tutorials/10_agentic/10_temporal/050_agent_chat_guardrails/README.md b/examples/tutorials/10_agentic/10_temporal/050_agent_chat_guardrails/README.md index 9eb75f98..8f6d3bc1 100644 --- a/examples/tutorials/10_agentic/10_temporal/050_agent_chat_guardrails/README.md +++ b/examples/tutorials/10_agentic/10_temporal/050_agent_chat_guardrails/README.md @@ -1,10 +1,27 @@ -# [Agentic] Agent Chat with Guardrails +# [Temporal] Agent Chat with Guardrails This tutorial demonstrates how to implement streaming multiturn tool-enabled chat with input and output guardrails using Temporal workflows in AgentEx agents. -## Overview +## What You'll Learn +- Adding safety guardrails to conversational agents +- Input validation and output filtering +- Implementing content moderation with Temporal +- When to block vs warn vs allow content -This example extends the basic agent chat functionality by adding guardrails that can filter both user inputs and AI outputs. This is useful for content moderation, compliance, or preventing certain topics from being discussed. +## Prerequisites +- Development environment set up (see [main repo README](https://github.com/scaleapi/scale-agentex)) +- Backend services running: `make dev` from repository root +- Temporal UI available at http://localhost:8233 +- Understanding of agent chat patterns (see [010_agent_chat](../010_agent_chat/)) + +## Quick Start + +```bash +cd examples/tutorials/10_agentic/10_temporal/050_agent_chat_guardrails +uv run agentex agents run --manifest manifest.yaml +``` + +**Monitor:** Open Temporal UI at http://localhost:8233 to see guardrail checks as workflow activities. ## Guardrails @@ -39,4 +56,15 @@ The guardrails are implemented as functions that: - `output_info`: Metadata about the check - `rejection_message`: Custom message shown when content is blocked -See `workflow.py` for the complete implementation. \ No newline at end of file +See `workflow.py` for the complete implementation. + +## When to Use +- Content moderation and safety requirements +- Compliance with regulatory restrictions +- Brand safety and reputation protection +- Preventing agents from discussing sensitive topics + +## Why This Matters +Production agents need safety rails. This pattern shows how to implement content filtering without sacrificing the benefits of Temporal workflows. Guardrail checks become durable activities, visible in Temporal UI for audit and debugging. + +**Next:** [060_open_ai_agents_sdk_hello_world](../060_open_ai_agents_sdk_hello_world/) - Integrate OpenAI Agents SDK with Temporal \ No newline at end of file diff --git a/examples/tutorials/10_agentic/10_temporal/060_open_ai_agents_sdk_hello_world/README.md b/examples/tutorials/10_agentic/10_temporal/060_open_ai_agents_sdk_hello_world/README.md index c46722b8..6594f105 100644 --- a/examples/tutorials/10_agentic/10_temporal/060_open_ai_agents_sdk_hello_world/README.md +++ b/examples/tutorials/10_agentic/10_temporal/060_open_ai_agents_sdk_hello_world/README.md @@ -1,317 +1,105 @@ -# example-tutorial - AgentEx Temporal Agent Template +# [Temporal] OpenAI Agents SDK - Hello World -This is a starter template for building asynchronous agents with the AgentEx framework and Temporal. It provides a basic implementation of the Agent 2 Client Protocol (ACP) with Temporal workflow support to help you get started quickly. +**Part of the [OpenAI SDK + Temporal integration series](../README.md)** ## What You'll Learn -- **Tasks**: A task is a grouping mechanism for related messages. Think of it as a conversation thread or a session. -- **Messages**: Messages are communication objects within a task. They can contain text, data, or instructions. -- **ACP Events**: The agent responds to four main events: - - `task_received`: When a new task is created - - `task_message_received`: When a message is sent within a task - - `task_approved`: When a task is approved - - `task_canceled`: When a task is canceled -- **Temporal Workflows**: Long-running processes that can handle complex state management and async operations +The OpenAI Agents SDK plugin automatically converts LLM calls into durable Temporal activities. When `Runner.run()` executes, the LLM invocation becomes an `invoke_model_activity` visible in Temporal UI with full observability, automatic retries, and durability. -## Running the Agent +**Key insight:** You don't need to wrap agent calls in activities manually - the plugin handles this automatically, making non-deterministic LLM calls work seamlessly in Temporal workflows. -1. Run the agent locally: -```bash -agentex agents run --manifest manifest.yaml -``` - -The agent will start on port 8000 and print messages whenever it receives any of the ACP events. - -## What's Inside - -This template: -- Sets up a basic ACP server with Temporal integration -- Handles each of the required ACP events -- Provides a foundation for building complex async agents -- Includes Temporal workflow and activity definitions - -## Next Steps - -For more advanced agent development, check out the AgentEx tutorials: - -- **Tutorials 00-08**: Learn about building synchronous agents with ACP -- **Tutorials 09-10**: Learn how to use Temporal to power asynchronous agents - - Tutorial 09: Basic Temporal workflow setup - - Tutorial 10: Advanced Temporal patterns and best practices - -These tutorials will help you understand: -- How to handle long-running tasks -- Implementing state machines -- Managing complex workflows -- Best practices for async agent development - -## The Manifest File - -The `manifest.yaml` file is your agent's configuration file. It defines: -- How your agent should be built and packaged -- What files are included in your agent's Docker image -- Your agent's name and description -- Local development settings (like the port your agent runs on) -- Temporal worker configuration - -This file is essential for both local development and deployment of your agent. - -## Project Structure - -``` -example_tutorial/ -├── project/ # Your agent's code -│ ├── __init__.py -│ ├── acp.py # ACP server and event handlers -│ ├── workflow.py # Temporal workflow definitions -│ ├── activities.py # Temporal activity definitions -│ └── run_worker.py # Temporal worker setup -├── Dockerfile # Container definition -├── manifest.yaml # Deployment config -├── dev.ipynb # Development notebook for testing - -└── pyproject.toml # Dependencies (uv) - -``` - -## Development +## Prerequisites +- Development environment set up (see [main repo README](https://github.com/scaleapi/scale-agentex)) +- Backend services running: `make dev` from repository root (includes Temporal) +- Temporal UI available at http://localhost:8233 +- OpenAI API key configured (see setup below) +- Understanding of Temporal workflows (see [000_hello_acp](../000_hello_acp/)) -### 1. Customize Event Handlers -- Modify the handlers in `acp.py` to implement your agent's logic -- Add your own tools and capabilities -- Implement custom state management +## Setup -### 2. Test Your Agent with the Development Notebook -Use the included `dev.ipynb` Jupyter notebook to test your agent interactively: +This tutorial uses the OpenAI Agents SDK plugin, which needs to be added in two places: -```bash -# Start Jupyter notebook (make sure you have jupyter installed) -jupyter notebook dev.ipynb - -# Or use VS Code to open the notebook directly -code dev.ipynb -``` - -The notebook includes: -- **Setup**: Connect to your local AgentEx backend -- **Task creation**: Create a new task for the conversation -- **Event sending**: Send events to the agent and get responses -- **Async message subscription**: Subscribe to server-side events to receive agent responses -- **Rich message display**: Beautiful formatting with timestamps and author information - -The notebook automatically uses your agent name (`example-tutorial`) and demonstrates the agentic ACP workflow: create task → send event → subscribe to responses. - -### 3. Develop Temporal Workflows -- Edit `workflow.py` to define your agent's async workflow logic -- Modify `activities.py` to add custom activities -- Use `run_worker.py` to configure the Temporal worker - -### 4. Manage Dependencies - - -You chose **uv** for package management. Here's how to work with dependencies: - -```bash -# Add new dependencies -agentex uv add requests openai anthropic - -# Add Temporal-specific dependencies (already included) -agentex uv add temporalio - -# Install/sync dependencies -agentex uv sync +### 1. Add Plugin to ACP (`project/acp.py`) +```python +from agentex.lib.plugins.openai_agents import OpenAIAgentsPlugin -# Run commands with uv -uv run agentex agents run --manifest manifest.yaml +acp = FastACP.create( + config=TemporalACPConfig( + plugins=[OpenAIAgentsPlugin()] # Add this + ) +) ``` -**Benefits of uv:** -- Faster dependency resolution and installation -- Better dependency isolation -- Modern Python packaging standards - - - -### 5. Configure Credentials -- Add any required credentials to your manifest.yaml -- For local development, create a `.env` file in the project directory -- Use `load_dotenv()` only in development mode: - +### 2. Add Plugin to Worker (`project/run_worker.py`) ```python -import os -from dotenv import load_dotenv +from agentex.lib.plugins.openai_agents import OpenAIAgentsPlugin -if os.environ.get("ENVIRONMENT") == "development": - load_dotenv() +worker = AgentexWorker( + task_queue=task_queue_name, + plugins=[OpenAIAgentsPlugin()], # Add this +) ``` -## Local Development - -### 1. Start the Agentex Backend -```bash -# Navigate to the backend directory -cd agentex - -# Start all services using Docker Compose -make dev - -# Optional: In a separate terminal, use lazydocker for a better UI (everything should say "healthy") -lzd +### 3. Configure OpenAI API Key +Add to `manifest.yaml`: +```yaml +secrets: + - name: OPENAI_API_KEY + value: "your-openai-api-key-here" ``` -### 2. Setup Your Agent's requirements/pyproject.toml -```bash -agentex uv sync [--group editable-apy] -source .venv/bin/activate +Or set in `.env` file: `OPENAI_API_KEY=your-key-here` -# OR -conda create -n example_tutorial python=3.12 -conda activate example_tutorial -pip install -r requirements.txt -``` -### 3. Run Your Agent -```bash -# From this directory -export ENVIRONMENT=development && [uv run] agentex agents run --manifest manifest.yaml -``` -4. **Interact with your agent** +## Quick Start -Option 0: CLI (deprecated - to be replaced once a new CLI is implemented - please use the web UI for now!) ```bash -# Submit a task via CLI -agentex tasks submit --agent example-tutorial --task "Your task here" -``` - -Option 1: Web UI -```bash -# Start the local web interface -cd agentex-web -make dev - -# Then open http://localhost:3000 in your browser to chat with your agent +cd examples/tutorials/10_agentic/10_temporal/060_open_ai_agents_sdk_hello_world +uv run agentex agents run --manifest manifest.yaml ``` -## Development Tips +**Monitor:** Open Temporal UI at http://localhost:8233 to see automatic activity creation. -### Environment Variables -- Set environment variables in project/.env for any required credentials -- Or configure them in the manifest.yaml under the `env` section -- The `.env` file is automatically loaded in development mode +## Try It -### Local Testing -- Use `export ENVIRONMENT=development` before running your agent -- This enables local service discovery and debugging features -- Your agent will automatically connect to locally running services +1. Send a message to the agent (it responds in haikus) +2. Check the agent response: -### Temporal-Specific Tips -- Monitor workflows in the Temporal Web UI at http://localhost:8080 -- Use the Temporal CLI for advanced workflow management -- Check workflow logs for debugging async operations - -### Debugging -- Check agent logs in the terminal where you ran the agent -- Use the web UI to inspect task history and responses -- Monitor backend services with `lzd` (LazyDocker) -- Use Temporal Web UI for workflow debugging - -### To build the agent Docker image locally (normally not necessary): - -1. Build the agent image: -```bash -agentex agents build --manifest manifest.yaml -``` +![Agent Response](../_images/hello_world_response.png) -## Advanced Features +3. Open Temporal UI at http://localhost:8233 +4. Find your workflow execution +5. Look for the `invoke_model_activity` - this was created automatically: -### Temporal Workflows -Extend your agent with sophisticated async workflows: +![Temporal UI](../_images/hello_world_temporal.png) -```python -# In project/workflow.py -@workflow.defn -class MyWorkflow(BaseWorkflow): - async def complex_operation(self): - # Multi-step async operations - # Error handling and retries - # State management - pass -``` +6. Inspect the activity to see: + - Input parameters (your message) + - Output (agent's haiku response) + - Execution time + - Retry attempts (if any failures occurred) -### Custom Activities -Add custom activities for external operations. **Important**: Always specify appropriate timeouts (recommended: 10 minutes): +## Key Code ```python -# In project/activities.py -from datetime import timedelta -from temporalio import activity -from temporalio.common import RetryPolicy - -@activity.defn(name="call_external_api") -async def call_external_api(data): - # HTTP requests, database operations, etc. - pass - -# In your workflow, call it with a timeout: -result = await workflow.execute_activity( - "call_external_api", - data, - start_to_close_timeout=timedelta(minutes=10), # Recommended: 10 minute timeout - heartbeat_timeout=timedelta(minutes=1), # Optional: heartbeat monitoring - retry_policy=RetryPolicy(maximum_attempts=3) # Optional: retry policy -) - -# Don't forget to register your custom activities in run_worker.py: -# all_activities = get_all_activities() + [your_custom_activity_function] +# This simple call automatically becomes a durable Temporal activity: +agent = Agent(name="Haiku Assistant", instructions="...") +result = await Runner.run(agent, user_message) ``` -### Integration with External Services - -```bash -# Add service clients -agentex uv add httpx requests-oauthlib - -# Add AI/ML libraries -agentex uv add openai anthropic transformers - -# Add database clients -agentex uv add asyncpg redis -``` - - -## Troubleshooting - -### Common Issues - -1. **Agent not appearing in web UI** - - Check if agent is running on port 8000 - - Verify `ENVIRONMENT=development` is set - - Check agent logs for errors - -2. **Temporal workflow issues** - - Check Temporal Web UI at http://localhost:8080 - - Verify Temporal server is running in backend services - - Check workflow logs for specific errors - -3. **Dependency issues** - - - Run `agentex uv sync` to ensure all dependencies are installed - - Verify temporalio is properly installed +The magic happens behind the scenes - no manual activity wrapping needed. The conversation is now durable and survives process restarts. +## Why This Matters -4. **Port conflicts** - - Check if another service is using port 8000 - - Use `lsof -i :8000` to find conflicting processes +**Durability:** If your worker crashes mid-conversation, Temporal resumes exactly where it left off. No lost context, no repeated work. -### Temporal-Specific Troubleshooting +**Observability:** Every LLM call is tracked as an activity with full execution history. -1. **Workflow not starting** - - Check if Temporal server is running (`docker ps`) - - Verify task queue configuration in `run_worker.py` - - Check workflow registration in the worker +**Reliability:** Failed LLM calls are automatically retried with exponential backoff. -2. **Activity failures** - - Check activity logs in the console - - Verify activity registration - - Check for timeout issues +## When to Use +- Building agents with OpenAI's SDK +- Need durability for LLM calls +- Want automatic activity creation without manual wrapping +- Leveraging OpenAI's agent patterns with Temporal's durability -Happy building with Temporal! 🚀⚡ \ No newline at end of file +**Next:** [070_open_ai_agents_sdk_tools](../070_open_ai_agents_sdk_tools/) - Add durable tools to your agents diff --git a/examples/tutorials/10_agentic/10_temporal/070_open_ai_agents_sdk_tools/README.md b/examples/tutorials/10_agentic/10_temporal/070_open_ai_agents_sdk_tools/README.md index c46722b8..9dee3544 100644 --- a/examples/tutorials/10_agentic/10_temporal/070_open_ai_agents_sdk_tools/README.md +++ b/examples/tutorials/10_agentic/10_temporal/070_open_ai_agents_sdk_tools/README.md @@ -1,317 +1,180 @@ -# example-tutorial - AgentEx Temporal Agent Template +# [Temporal] OpenAI Agents SDK - Tools -This is a starter template for building asynchronous agents with the AgentEx framework and Temporal. It provides a basic implementation of the Agent 2 Client Protocol (ACP) with Temporal workflow support to help you get started quickly. +**Part of the [OpenAI SDK + Temporal integration series](../README.md)** → Previous: [060 Hello World](../060_open_ai_agents_sdk_hello_world/) ## What You'll Learn -- **Tasks**: A task is a grouping mechanism for related messages. Think of it as a conversation thread or a session. -- **Messages**: Messages are communication objects within a task. They can contain text, data, or instructions. -- **ACP Events**: The agent responds to four main events: - - `task_received`: When a new task is created - - `task_message_received`: When a message is sent within a task - - `task_approved`: When a task is approved - - `task_canceled`: When a task is canceled -- **Temporal Workflows**: Long-running processes that can handle complex state management and async operations +Two patterns for making agent tools durable with Temporal: -## Running the Agent +**Pattern 1: `activity_as_tool()`** - Single activity per tool call +- Use for: Single API calls, DB queries, external operations +- Example: `get_weather` tool → creates one `get_weather` activity +- 1:1 mapping between tool calls and activities -1. Run the agent locally: -```bash -agentex agents run --manifest manifest.yaml -``` - -The agent will start on port 8000 and print messages whenever it receives any of the ACP events. - -## What's Inside - -This template: -- Sets up a basic ACP server with Temporal integration -- Handles each of the required ACP events -- Provides a foundation for building complex async agents -- Includes Temporal workflow and activity definitions - -## Next Steps - -For more advanced agent development, check out the AgentEx tutorials: - -- **Tutorials 00-08**: Learn about building synchronous agents with ACP -- **Tutorials 09-10**: Learn how to use Temporal to power asynchronous agents - - Tutorial 09: Basic Temporal workflow setup - - Tutorial 10: Advanced Temporal patterns and best practices +**Pattern 2: Function tools with multiple activities** - Multiple activities per tool call +- Use for: Multi-step operations needing guaranteed sequencing +- Example: `move_money` tool → creates `withdraw_money` activity THEN `deposit_money` activity +- 1:many mapping - your code controls execution order, not the LLM +- Ensures atomic operations (withdraw always happens before deposit) -These tutorials will help you understand: -- How to handle long-running tasks -- Implementing state machines -- Managing complex workflows -- Best practices for async agent development - -## The Manifest File - -The `manifest.yaml` file is your agent's configuration file. It defines: -- How your agent should be built and packaged -- What files are included in your agent's Docker image -- Your agent's name and description -- Local development settings (like the port your agent runs on) -- Temporal worker configuration - -This file is essential for both local development and deployment of your agent. - -## Project Structure - -``` -example_tutorial/ -├── project/ # Your agent's code -│ ├── __init__.py -│ ├── acp.py # ACP server and event handlers -│ ├── workflow.py # Temporal workflow definitions -│ ├── activities.py # Temporal activity definitions -│ └── run_worker.py # Temporal worker setup -├── Dockerfile # Container definition -├── manifest.yaml # Deployment config -├── dev.ipynb # Development notebook for testing - -└── pyproject.toml # Dependencies (uv) - -``` +## Prerequisites +- Development environment set up (see [main repo README](https://github.com/scaleapi/scale-agentex)) +- Backend services running: `make dev` from repository root +- Temporal UI available at http://localhost:8233 +- OpenAI Agents SDK plugin configured (see [060_hello_world](../060_open_ai_agents_sdk_hello_world/)) -## Development - -### 1. Customize Event Handlers -- Modify the handlers in `acp.py` to implement your agent's logic -- Add your own tools and capabilities -- Implement custom state management - -### 2. Test Your Agent with the Development Notebook -Use the included `dev.ipynb` Jupyter notebook to test your agent interactively: +## Quick Start ```bash -# Start Jupyter notebook (make sure you have jupyter installed) -jupyter notebook dev.ipynb - -# Or use VS Code to open the notebook directly -code dev.ipynb -``` - -The notebook includes: -- **Setup**: Connect to your local AgentEx backend -- **Task creation**: Create a new task for the conversation -- **Event sending**: Send events to the agent and get responses -- **Async message subscription**: Subscribe to server-side events to receive agent responses -- **Rich message display**: Beautiful formatting with timestamps and author information - -The notebook automatically uses your agent name (`example-tutorial`) and demonstrates the agentic ACP workflow: create task → send event → subscribe to responses. - -### 3. Develop Temporal Workflows -- Edit `workflow.py` to define your agent's async workflow logic -- Modify `activities.py` to add custom activities -- Use `run_worker.py` to configure the Temporal worker - -### 4. Manage Dependencies - - -You chose **uv** for package management. Here's how to work with dependencies: - -```bash -# Add new dependencies -agentex uv add requests openai anthropic - -# Add Temporal-specific dependencies (already included) -agentex uv add temporalio - -# Install/sync dependencies -agentex uv sync - -# Run commands with uv +cd examples/tutorials/10_agentic/10_temporal/070_open_ai_agents_sdk_tools uv run agentex agents run --manifest manifest.yaml ``` -**Benefits of uv:** -- Faster dependency resolution and installation -- Better dependency isolation -- Modern Python packaging standards +**Monitor:** Open Temporal UI at http://localhost:8233 to see tool calls as activities. +## Try It +### Pattern 1: Single Activity Tool -### 5. Configure Credentials -- Add any required credentials to your manifest.yaml -- For local development, create a `.env` file in the project directory -- Use `load_dotenv()` only in development mode: +Ask "What's the weather in San Francisco?" -```python -import os -from dotenv import load_dotenv - -if os.environ.get("ENVIRONMENT") == "development": - load_dotenv() -``` - -## Local Development +1. Check the agent response: -### 1. Start the Agentex Backend -```bash -# Navigate to the backend directory -cd agentex - -# Start all services using Docker Compose -make dev - -# Optional: In a separate terminal, use lazydocker for a better UI (everything should say "healthy") -lzd -``` +![Weather Response](../_images/weather_response.png) -### 2. Setup Your Agent's requirements/pyproject.toml -```bash -agentex uv sync [--group editable-apy] -source .venv/bin/activate - -# OR -conda create -n example_tutorial python=3.12 -conda activate example_tutorial -pip install -r requirements.txt -``` -### 3. Run Your Agent -```bash -# From this directory -export ENVIRONMENT=development && [uv run] agentex agents run --manifest manifest.yaml -``` -4. **Interact with your agent** - -Option 0: CLI (deprecated - to be replaced once a new CLI is implemented - please use the web UI for now!) -```bash -# Submit a task via CLI -agentex tasks submit --agent example-tutorial --task "Your task here" -``` +2. Open Temporal UI (localhost:8233) +3. See a single `get_weather` activity created: -Option 1: Web UI -```bash -# Start the local web interface -cd agentex-web -make dev +![Weather Activity](../_images/weather_activity_tool.png) -# Then open http://localhost:3000 in your browser to chat with your agent -``` +The activity shows the external call with retry capability. Each step (model invocation → tool call → model invocation) is durable. -## Development Tips +### Pattern 2: Multi-Activity Tool (Optional) -### Environment Variables -- Set environment variables in project/.env for any required credentials -- Or configure them in the manifest.yaml under the `env` section -- The `.env` file is automatically loaded in development mode +To try the advanced banking example, uncomment the `move_money` sections in the code, then ask to move money. -### Local Testing -- Use `export ENVIRONMENT=development` before running your agent -- This enables local service discovery and debugging features -- Your agent will automatically connect to locally running services +1. Check the agent response: -### Temporal-Specific Tips -- Monitor workflows in the Temporal Web UI at http://localhost:8080 -- Use the Temporal CLI for advanced workflow management -- Check workflow logs for debugging async operations +![Money Transfer Response](../_images/move_money_response.png) -### Debugging -- Check agent logs in the terminal where you ran the agent -- Use the web UI to inspect task history and responses -- Monitor backend services with `lzd` (LazyDocker) -- Use Temporal Web UI for workflow debugging +2. Open Temporal UI and see TWO sequential activities: -### To build the agent Docker image locally (normally not necessary): +![Money Transfer Workflow](../_images/move_money_temporal.png) -1. Build the agent image: -```bash -agentex agents build --manifest manifest.yaml -``` +- First: `withdraw_money` activity executes +- Then: `deposit_money` activity executes +- Each activity shows its parameters and execution time -## Advanced Features +**Critical insight:** If the system crashes after withdraw but before deposit, Temporal resumes exactly where it left off. The deposit will still happen - guaranteed transactional integrity. -### Temporal Workflows -Extend your agent with sophisticated async workflows: +## Key Code +### Pattern 1: Single Activity Tool ```python -# In project/workflow.py -@workflow.defn -class MyWorkflow(BaseWorkflow): - async def complex_operation(self): - # Multi-step async operations - # Error handling and retries - # State management - pass +# Define the activity +@activity.defn +async def get_weather(city: str) -> str: + """Get the weather for a given city""" + # This could be an API call - Temporal handles retries + return f"The weather in {city} is sunny" + +# Use activity_as_tool to convert it +weather_agent = Agent( + name="Weather Assistant", + instructions="Use the get_weather tool to answer weather questions.", + tools=[ + activity_as_tool(get_weather, start_to_close_timeout=timedelta(seconds=10)) + ] +) ``` -### Custom Activities -Add custom activities for external operations. **Important**: Always specify appropriate timeouts (recommended: 10 minutes): - +### Pattern 2: Multi-Activity Tool ```python -# In project/activities.py -from datetime import timedelta -from temporalio import activity -from temporalio.common import RetryPolicy - -@activity.defn(name="call_external_api") -async def call_external_api(data): - # HTTP requests, database operations, etc. - pass - -# In your workflow, call it with a timeout: -result = await workflow.execute_activity( - "call_external_api", - data, - start_to_close_timeout=timedelta(minutes=10), # Recommended: 10 minute timeout - heartbeat_timeout=timedelta(minutes=1), # Optional: heartbeat monitoring - retry_policy=RetryPolicy(maximum_attempts=3) # Optional: retry policy +# Define individual activities +@activity.defn +async def withdraw_money(from_account: str, amount: float) -> str: + # Simulate API call + await asyncio.sleep(5) + return f"Withdrew ${amount} from {from_account}" + +@activity.defn +async def deposit_money(to_account: str, amount: float) -> str: + # Simulate API call + await asyncio.sleep(10) + return f"Deposited ${amount} into {to_account}" + +# Create a function tool that orchestrates both activities +@function_tool +async def move_money(from_account: str, to_account: str, amount: float) -> str: + """Move money from one account to another""" + + # Step 1: Withdraw (becomes an activity) + await workflow.start_activity( + "withdraw_money", + args=[from_account, amount], + start_to_close_timeout=timedelta(days=1) + ) + + # Step 2: Deposit (becomes an activity) + await workflow.start_activity( + "deposit_money", + args=[to_account, amount], + start_to_close_timeout=timedelta(days=1) + ) + + return "Money transferred successfully" + +# Use the tool in your agent +money_agent = Agent( + name="Money Mover", + instructions="Use move_money to transfer funds between accounts.", + tools=[move_money] ) - -# Don't forget to register your custom activities in run_worker.py: -# all_activities = get_all_activities() + [your_custom_activity_function] ``` -### Integration with External Services - -```bash -# Add service clients -agentex uv add httpx requests-oauthlib - -# Add AI/ML libraries -agentex uv add openai anthropic transformers - -# Add database clients -agentex uv add asyncpg redis -``` - - -## Troubleshooting +## When to Use Each Pattern -### Common Issues +### Use Pattern 1 when: +- Tool performs a single external operation (API call, DB query) +- Operation is already idempotent +- No sequencing guarantees needed -1. **Agent not appearing in web UI** - - Check if agent is running on port 8000 - - Verify `ENVIRONMENT=development` is set - - Check agent logs for errors +### Use Pattern 2 when: +- Tool requires multiple sequential operations +- Order must be guaranteed (withdraw THEN deposit) +- Operations need to be atomic from the agent's perspective +- You want transactional integrity across steps -2. **Temporal workflow issues** - - Check Temporal Web UI at http://localhost:8080 - - Verify Temporal server is running in backend services - - Check workflow logs for specific errors +## Why This Matters -3. **Dependency issues** +**Without Temporal:** If you withdraw money but crash before depositing, you're stuck in a broken state. The money is gone from the source account with no way to recover. - - Run `agentex uv sync` to ensure all dependencies are installed - - Verify temporalio is properly installed +**With Temporal (Pattern 2):** +- Guaranteed execution with exact resumption after failures +- If the system crashes after withdraw, Temporal resumes and completes deposit +- Each step is tracked and retried independently +- Full observability of the entire operation +**Key insight:** Pattern 2 moves sequencing control from the LLM (which might call tools in wrong order) to your deterministic code (which guarantees correct order). The LLM still decides *when* to call the tool, but your code controls *how* the operations execute. -4. **Port conflicts** - - Check if another service is using port 8000 - - Use `lsof -i :8000` to find conflicting processes +This makes agents production-ready for: +- Financial transactions +- Order fulfillment workflows +- Multi-step API integrations +- Any operation where partial completion is dangerous -### Temporal-Specific Troubleshooting +## When to Use -1. **Workflow not starting** - - Check if Temporal server is running (`docker ps`) - - Verify task queue configuration in `run_worker.py` - - Check workflow registration in the worker +**Pattern 1 (activity_as_tool):** +- Single API calls +- Database queries +- External service integrations +- Operations that are naturally atomic -2. **Activity failures** - - Check activity logs in the console - - Verify activity registration - - Check for timeout issues +**Pattern 2 (Multi-activity tools):** +- Financial transactions requiring sequencing +- Multi-step operations with dependencies +- Operations where order matters critically +- Workflows needing guaranteed atomicity -Happy building with Temporal! 🚀⚡ \ No newline at end of file +**Next:** [080_open_ai_agents_sdk_human_in_the_loop](../080_open_ai_agents_sdk_human_in_the_loop/) - Add human approval workflows diff --git a/examples/tutorials/10_agentic/10_temporal/080_open_ai_agents_sdk_human_in_the_loop/README.md b/examples/tutorials/10_agentic/10_temporal/080_open_ai_agents_sdk_human_in_the_loop/README.md index c46722b8..2c7ea850 100644 --- a/examples/tutorials/10_agentic/10_temporal/080_open_ai_agents_sdk_human_in_the_loop/README.md +++ b/examples/tutorials/10_agentic/10_temporal/080_open_ai_agents_sdk_human_in_the_loop/README.md @@ -1,317 +1,199 @@ -# example-tutorial - AgentEx Temporal Agent Template +# [Temporal] OpenAI Agents SDK - Human in the Loop -This is a starter template for building asynchronous agents with the AgentEx framework and Temporal. It provides a basic implementation of the Agent 2 Client Protocol (ACP) with Temporal workflow support to help you get started quickly. +**Part of the [OpenAI SDK + Temporal integration series](../README.md)** → Previous: [070 Tools](../070_open_ai_agents_sdk_tools/) ## What You'll Learn -- **Tasks**: A task is a grouping mechanism for related messages. Think of it as a conversation thread or a session. -- **Messages**: Messages are communication objects within a task. They can contain text, data, or instructions. -- **ACP Events**: The agent responds to four main events: - - `task_received`: When a new task is created - - `task_message_received`: When a message is sent within a task - - `task_approved`: When a task is approved - - `task_canceled`: When a task is canceled -- **Temporal Workflows**: Long-running processes that can handle complex state management and async operations +How to pause agent execution and wait indefinitely for human approval using Temporal's child workflows and signals. The agent can wait for hours, days, or weeks for human input without consuming resources - and if the system crashes, it resumes exactly where it left off. -## Running the Agent +**Pattern:** +1. Agent calls `wait_for_confirmation` tool +2. Tool spawns a child workflow that waits for a signal +3. Human approves/rejects via Temporal CLI or web UI +4. Child workflow completes, agent continues with the response -1. Run the agent locally: -```bash -agentex agents run --manifest manifest.yaml -``` - -The agent will start on port 8000 and print messages whenever it receives any of the ACP events. - -## What's Inside - -This template: -- Sets up a basic ACP server with Temporal integration -- Handles each of the required ACP events -- Provides a foundation for building complex async agents -- Includes Temporal workflow and activity definitions - -## Next Steps - -For more advanced agent development, check out the AgentEx tutorials: - -- **Tutorials 00-08**: Learn about building synchronous agents with ACP -- **Tutorials 09-10**: Learn how to use Temporal to power asynchronous agents - - Tutorial 09: Basic Temporal workflow setup - - Tutorial 10: Advanced Temporal patterns and best practices - -These tutorials will help you understand: -- How to handle long-running tasks -- Implementing state machines -- Managing complex workflows -- Best practices for async agent development - -## The Manifest File - -The `manifest.yaml` file is your agent's configuration file. It defines: -- How your agent should be built and packaged -- What files are included in your agent's Docker image -- Your agent's name and description -- Local development settings (like the port your agent runs on) -- Temporal worker configuration - -This file is essential for both local development and deployment of your agent. - -## Project Structure - -``` -example_tutorial/ -├── project/ # Your agent's code -│ ├── __init__.py -│ ├── acp.py # ACP server and event handlers -│ ├── workflow.py # Temporal workflow definitions -│ ├── activities.py # Temporal activity definitions -│ └── run_worker.py # Temporal worker setup -├── Dockerfile # Container definition -├── manifest.yaml # Deployment config -├── dev.ipynb # Development notebook for testing - -└── pyproject.toml # Dependencies (uv) - -``` +## New Temporal Concepts -## Development +### Signals +Signals are a way for external systems to interact with running workflows. Think of them as secure, durable messages sent to your workflow from the outside world. -### 1. Customize Event Handlers -- Modify the handlers in `acp.py` to implement your agent's logic -- Add your own tools and capabilities -- Implement custom state management +**Use cases:** +- User approving/rejecting an action in a web app +- Payment confirmation triggering shipping +- Live data feeds (stock prices) triggering trades +- Webhooks from external services updating workflow state -### 2. Test Your Agent with the Development Notebook -Use the included `dev.ipynb` Jupyter notebook to test your agent interactively: +**How it works:** Define a function in your workflow class with the `@workflow.signal` decorator. External systems can then send signals using: +- Temporal SDK (by workflow ID) +- Another Temporal workflow +- Temporal CLI +- Temporal Web UI -```bash -# Start Jupyter notebook (make sure you have jupyter installed) -jupyter notebook dev.ipynb - -# Or use VS Code to open the notebook directly -code dev.ipynb -``` +[Learn more about signals](https://docs.temporal.io/develop/python/message-passing#send-signal-from-client) -The notebook includes: -- **Setup**: Connect to your local AgentEx backend -- **Task creation**: Create a new task for the conversation -- **Event sending**: Send events to the agent and get responses -- **Async message subscription**: Subscribe to server-side events to receive agent responses -- **Rich message display**: Beautiful formatting with timestamps and author information +### Child Workflows +Child workflows are like spawning a new workflow from within your current workflow. Similar to calling a function in traditional programming, but the child workflow: +- Runs independently with its own execution history +- Inherits all Temporal durability guarantees +- Can be monitored separately in Temporal UI +- Continues running even if the parent has issues -The notebook automatically uses your agent name (`example-tutorial`) and demonstrates the agentic ACP workflow: create task → send event → subscribe to responses. +**Why use child workflows for human-in-the-loop?** +- The parent workflow can continue processing while waiting +- The child workflow can wait indefinitely for human input +- Full isolation between waiting logic and main agent logic +- Clean separation of concerns -### 3. Develop Temporal Workflows -- Edit `workflow.py` to define your agent's async workflow logic -- Modify `activities.py` to add custom activities -- Use `run_worker.py` to configure the Temporal worker +[Learn more about child workflows](https://docs.temporal.io/develop/python/child-workflows) -### 4. Manage Dependencies +## Prerequisites +- Development environment set up (see [main repo README](https://github.com/scaleapi/scale-agentex)) +- Backend services running: `make dev` from repository root +- Temporal UI available at http://localhost:8233 +- OpenAI Agents SDK plugin configured (see [060_hello_world](../060_open_ai_agents_sdk_hello_world/)) +- Understanding of tools (see [070_tools](../070_open_ai_agents_sdk_tools/)) - -You chose **uv** for package management. Here's how to work with dependencies: +## Quick Start ```bash -# Add new dependencies -agentex uv add requests openai anthropic - -# Add Temporal-specific dependencies (already included) -agentex uv add temporalio - -# Install/sync dependencies -agentex uv sync - -# Run commands with uv +cd examples/tutorials/10_agentic/10_temporal/080_open_ai_agents_sdk_human_in_the_loop uv run agentex agents run --manifest manifest.yaml ``` -**Benefits of uv:** -- Faster dependency resolution and installation -- Better dependency isolation -- Modern Python packaging standards +**Monitor:** Open Temporal UI at http://localhost:8233 to see child workflows and signals. +## Try It +1. Ask the agent to do something that requires approval (e.g., "Order 100 widgets") +2. The agent will call `wait_for_confirmation` and pause +3. Open Temporal UI (localhost:8233) +4. Find the parent workflow - you'll see it's waiting on the child workflow: -### 5. Configure Credentials -- Add any required credentials to your manifest.yaml -- For local development, create a `.env` file in the project directory -- Use `load_dotenv()` only in development mode: - -```python -import os -from dotenv import load_dotenv - -if os.environ.get("ENVIRONMENT") == "development": - load_dotenv() -``` - -## Local Development - -### 1. Start the Agentex Backend -```bash -# Navigate to the backend directory -cd agentex - -# Start all services using Docker Compose -make dev - -# Optional: In a separate terminal, use lazydocker for a better UI (everything should say "healthy") -lzd -``` +![Parent Workflow Waiting](../_images/human_in_the_loop_workflow.png) -### 2. Setup Your Agent's requirements/pyproject.toml -```bash -agentex uv sync [--group editable-apy] -source .venv/bin/activate +5. Find the child workflow - it's waiting for a signal: -# OR -conda create -n example_tutorial python=3.12 -conda activate example_tutorial -pip install -r requirements.txt -``` -### 3. Run Your Agent -```bash -# From this directory -export ENVIRONMENT=development && [uv run] agentex agents run --manifest manifest.yaml -``` -4. **Interact with your agent** +![Child Workflow Waiting](../_images/human_in_the_loop_child_workflow.png) -Option 0: CLI (deprecated - to be replaced once a new CLI is implemented - please use the web UI for now!) -```bash -# Submit a task via CLI -agentex tasks submit --agent example-tutorial --task "Your task here" -``` +6. Send approval signal via CLI: -Option 1: Web UI ```bash -# Start the local web interface -cd agentex-web -make dev - -# Then open http://localhost:3000 in your browser to chat with your agent +temporal workflow signal \ + --workflow-id="" \ + --name="fulfill_order_signal" \ + --input=true ``` -## Development Tips - -### Environment Variables -- Set environment variables in project/.env for any required credentials -- Or configure them in the manifest.yaml under the `env` section -- The `.env` file is automatically loaded in development mode - -### Local Testing -- Use `export ENVIRONMENT=development` before running your agent -- This enables local service discovery and debugging features -- Your agent will automatically connect to locally running services +7. Watch both workflows complete - the agent resumes and finishes the action -### Temporal-Specific Tips -- Monitor workflows in the Temporal Web UI at http://localhost:8080 -- Use the Temporal CLI for advanced workflow management -- Check workflow logs for debugging async operations +## Key Code -### Debugging -- Check agent logs in the terminal where you ran the agent -- Use the web UI to inspect task history and responses -- Monitor backend services with `lzd` (LazyDocker) -- Use Temporal Web UI for workflow debugging - -### To build the agent Docker image locally (normally not necessary): - -1. Build the agent image: -```bash -agentex agents build --manifest manifest.yaml +### The Tool: Spawning a Child Workflow +```python +from agents import function_tool +from temporalio import workflow +from project.child_workflow import ChildWorkflow +from temporalio.workflow import ParentClosePolicy + +@function_tool +async def wait_for_confirmation(confirmation: bool) -> str: + """Wait for human confirmation before proceeding""" + + # Spawn a child workflow that will wait for a signal + result = await workflow.execute_child_workflow( + ChildWorkflow.on_task_create, + environment_variables.WORKFLOW_NAME + "_child", + id="child-workflow-id", + parent_close_policy=ParentClosePolicy.TERMINATE, + ) + + return result ``` -## Advanced Features - -### Temporal Workflows -Extend your agent with sophisticated async workflows: - +### The Child Workflow: Waiting for Signals ```python -# In project/workflow.py -@workflow.defn -class MyWorkflow(BaseWorkflow): - async def complex_operation(self): - # Multi-step async operations - # Error handling and retries - # State management - pass +import asyncio +from temporalio import workflow + +@workflow.defn(name=environment_variables.WORKFLOW_NAME + "_child") +class ChildWorkflow(): + def __init__(self): + # Queue to hold signals + self._pending_confirmation: asyncio.Queue[bool] = asyncio.Queue() + + @workflow.run + async def on_task_create(self, name: str) -> str: + logger.info(f"Child workflow started: {name}") + + # Wait indefinitely until we receive a signal + await workflow.wait_condition( + lambda: not self._pending_confirmation.empty() + ) + + # Signal received - complete the workflow + return "Task completed" + + @workflow.signal + async def fulfill_order_signal(self, success: bool) -> None: + """External systems call this to approve/reject""" + if success: + await self._pending_confirmation.put(True) ``` -### Custom Activities -Add custom activities for external operations. **Important**: Always specify appropriate timeouts (recommended: 10 minutes): - +### Using the Tool in Your Agent ```python -# In project/activities.py -from datetime import timedelta -from temporalio import activity -from temporalio.common import RetryPolicy - -@activity.defn(name="call_external_api") -async def call_external_api(data): - # HTTP requests, database operations, etc. - pass - -# In your workflow, call it with a timeout: -result = await workflow.execute_activity( - "call_external_api", - data, - start_to_close_timeout=timedelta(minutes=10), # Recommended: 10 minute timeout - heartbeat_timeout=timedelta(minutes=1), # Optional: heartbeat monitoring - retry_policy=RetryPolicy(maximum_attempts=3) # Optional: retry policy +confirm_order_agent = Agent( + name="Confirm Order", + instructions="When user asks to confirm an order, use wait_for_confirmation tool.", + tools=[wait_for_confirmation] ) -# Don't forget to register your custom activities in run_worker.py: -# all_activities = get_all_activities() + [your_custom_activity_function] -``` - -### Integration with External Services - -```bash -# Add service clients -agentex uv add httpx requests-oauthlib - -# Add AI/ML libraries -agentex uv add openai anthropic transformers - -# Add database clients -agentex uv add asyncpg redis +result = await Runner.run(confirm_order_agent, params.event.content.content) ``` - -## Troubleshooting - -### Common Issues - -1. **Agent not appearing in web UI** - - Check if agent is running on port 8000 - - Verify `ENVIRONMENT=development` is set - - Check agent logs for errors - -2. **Temporal workflow issues** - - Check Temporal Web UI at http://localhost:8080 - - Verify Temporal server is running in backend services - - Check workflow logs for specific errors - -3. **Dependency issues** - - - Run `agentex uv sync` to ensure all dependencies are installed - - Verify temporalio is properly installed - - -4. **Port conflicts** - - Check if another service is using port 8000 - - Use `lsof -i :8000` to find conflicting processes - -### Temporal-Specific Troubleshooting - -1. **Workflow not starting** - - Check if Temporal server is running (`docker ps`) - - Verify task queue configuration in `run_worker.py` - - Check workflow registration in the worker - -2. **Activity failures** - - Check activity logs in the console - - Verify activity registration - - Check for timeout issues - -Happy building with Temporal! 🚀⚡ \ No newline at end of file +## How It Works + +1. **Agent calls tool**: The LLM decides to call `wait_for_confirmation` +2. **Child workflow spawned**: A new workflow is created with its own ID +3. **Child waits**: Uses `workflow.wait_condition()` to block until signal arrives +4. **Parent waits**: Parent workflow is blocked waiting for child to complete +5. **Signal sent**: External system (CLI, web app, API) sends signal with workflow ID +6. **Signal received**: Child workflow's `fulfill_order_signal()` method is called +7. **Queue updated**: Signal handler adds item to queue +8. **Wait condition satisfied**: `wait_condition()` unblocks +9. **Child completes**: Returns result to parent +10. **Parent resumes**: Agent continues with the response + +**Critical insight:** At any point, if the system crashes: +- Both workflows are durable and will resume +- No context is lost +- The moment the signal arrives, execution continues + +## Why This Matters + +**Without Temporal:** If your system crashes while waiting for human approval, you lose all context about what was being approved. The user has to start over. + +**With Temporal:** +- The workflow waits durably (hours, days, weeks) +- If the system crashes and restarts, context is preserved +- The moment a human sends approval, workflow resumes exactly where it left off +- Full audit trail of who approved what and when + +**Production use cases:** +- **Financial transactions**: Agent initiates transfer, human approves +- **Legal document processing**: AI extracts data, lawyer reviews +- **Multi-step purchasing**: Agent negotiates, manager approves +- **Compliance workflows**: System flags issue, human decides action +- **High-stakes decisions**: Any operation requiring human judgment + +This pattern transforms agents from fully automated systems into **collaborative AI assistants** that know when to ask for help. + +## When to Use +- Financial transactions requiring approval +- High-stakes decisions needing human judgment +- Compliance workflows with mandatory review steps +- Legal or contractual operations +- Any operation where errors have serious consequences +- Workflows where AI assists but humans decide + +**Congratulations!** You've completed all AgentEx tutorials. You now know how to build production-ready agents from simple sync patterns to complex durable workflows with human oversight. diff --git a/examples/tutorials/README.md b/examples/tutorials/README.md new file mode 100644 index 00000000..ecdd2225 --- /dev/null +++ b/examples/tutorials/README.md @@ -0,0 +1,155 @@ +# AgentEx Tutorials + +Progressive tutorials for learning AgentEx from basics to production-ready patterns. + +## Prerequisites + +**Before starting any tutorial:** +1. Set up your development environment following the [main repo README](https://github.com/scaleapi/scale-agentex#setup) +2. Start backend services from repository root: + ```bash + cd /path/to/agentex-python + make dev + ``` +3. Verify Temporal UI is accessible at http://localhost:8233 + +For troubleshooting, see the [AgentEx debugging guide](https://github.com/scaleapi/scale-agentex#troubleshooting). + +## Learning Path + +```mermaid +graph TD + A[👋 Start Here] --> B[00_sync/000_hello_acp] + B --> C[00_sync/010_multiturn] + C --> D[00_sync/020_streaming] + + D --> E{Need Task
Management?} + E -->|Yes| F[10_agentic/00_base/
000_hello_acp] + E -->|No| G[Continue with
sync patterns] + + F --> H[00_base/010_multiturn] + H --> I[00_base/020_streaming] + I --> J[00_base/030_tracing] + J --> K[00_base/040_other_sdks] + K --> L[00_base/080_batch_events] + + L --> M{Building for
Production?} + M -->|Yes| N[10_temporal/
000_hello_acp] + M -->|No| O[00_base/090_multi_agent] + + N --> P[10_temporal/010_agent_chat] + P --> Q[10_temporal/020_state_machine] + Q --> R[10_temporal/030_custom_activities] + R --> S[10_temporal/050_guardrails] + + S --> T{Using
OpenAI SDK?} + T -->|Yes| U[10_temporal/060_openai_hello] + U --> V[10_temporal/070_openai_tools] + V --> W[10_temporal/080_openai_hitl] + T -->|No| X[🎉 Production Ready!] + W --> X + + style A fill:#e1f5e1 + style X fill:#fff3cd + style E fill:#e3f2fd + style M fill:#e3f2fd + style T fill:#e3f2fd +``` + +## Tutorial Structure + +### 00_sync/ - Synchronous Agents +Simple request-response patterns without task management. Start here if you're new to AgentEx. + +- **[000_hello_acp](00_sync/000_hello_acp/)** - Your first agent +- **[010_multiturn](00_sync/010_multiturn/)** - Maintaining conversation context +- **[020_streaming](00_sync/020_streaming/)** - Real-time response streaming + +**When to use:** Simple chatbots, stateless Q&A, quick prototypes + +--- + +### 10_agentic/ - Task-Based Agents + +#### 00_base/ - Non-Temporal Patterns +Task-based architecture without workflow orchestration. Adds task management on top of sync patterns. + +- **[000_hello_acp](10_agentic/00_base/000_hello_acp/)** - Task-based hello world +- **[010_multiturn](10_agentic/00_base/010_multiturn/)** - Multiturn with task management +- **[020_streaming](10_agentic/00_base/020_streaming/)** - Streaming with tasks +- **[030_tracing](10_agentic/00_base/030_tracing/)** - Observability with Scale Groundplane +- **[040_other_sdks](10_agentic/00_base/040_other_sdks/)** - Integrating OpenAI, Anthropic, etc. +- **[080_batch_events](10_agentic/00_base/080_batch_events/)** - Event batching (shows limitations → Temporal) +- **[090_multi_agent_non_temporal](10_agentic/00_base/090_multi_agent_non_temporal/)** - Complex multi-agent coordination + +**When to use:** Task tracking needed but workflows are simple, no durability requirements + +--- + +#### 10_temporal/ - Production Workflows +Durable, fault-tolerant agents with Temporal workflow orchestration. + +**Core Patterns:** +- **[000_hello_acp](10_agentic/10_temporal/000_hello_acp/)** - Temporal basics +- **[010_agent_chat](10_agentic/10_temporal/010_agent_chat/)** - Stateful conversations +- **[020_state_machine](10_agentic/10_temporal/020_state_machine/)** - Structured state management +- **[030_custom_activities](10_agentic/10_temporal/030_custom_activities/)** - Custom Temporal activities +- **[050_agent_chat_guardrails](10_agentic/10_temporal/050_agent_chat_guardrails/)** - Safety & validation + +**OpenAI Agents SDK Series:** +- **[060_openai_hello_world](10_agentic/10_temporal/060_open_ai_agents_sdk_hello_world/)** - Plugin-based agents +- **[070_openai_tools](10_agentic/10_temporal/070_open_ai_agents_sdk_tools/)** - Tool integration patterns +- **[080_openai_hitl](10_agentic/10_temporal/080_open_ai_agents_sdk_human_in_the_loop/)** - Human oversight workflows + +**When to use:** Production systems requiring durability, fault tolerance, long-running workflows, or complex state management + +--- + +## Quick Start + +```bash +# 1. Start backend services (from repo root) +make dev + +# 2. Navigate to a tutorial +cd examples/tutorials/00_sync/000_hello_acp + +# 3. Run it +uv run python hello_acp.py +``` + +## Common Commands + +```bash +# Format tutorial code (always scope to specific files you're modifying) +rye run format examples/tutorials/00_sync/000_hello_acp/ + +# Run all agentic tutorial tests +cd examples/tutorials +./run_all_agentic_tests.sh + +# Run specific tutorial test +cd examples/tutorials +uv run pytest 00_sync/000_hello_acp/ -v + +# Check Temporal UI (when running temporal tutorials) +open http://localhost:8233 +``` + +## Tutorial Categories at a Glance + +| Category | Tutorials | Focus | Use When | +|----------|-----------|-------|----------| +| **Sync** | 3 | Request-response basics | Learning fundamentals, simple chatbots | +| **Agentic Base** | 7 | Task management without workflows | Need task tracking, simple coordination | +| **Temporal** | 8 | Production-grade workflows | Need durability, fault tolerance, complex state | + +## Getting Help + +- **Each tutorial includes:** README explaining concepts, annotated source code, and tests +- **Common issues?** See [AgentEx troubleshooting guide](https://github.com/scaleapi/scale-agentex#troubleshooting) +- **Need more context?** Check the [main AgentEx documentation](https://github.com/scaleapi/scale-agentex) + +--- + +**Ready to start?** → Begin with [00_sync/000_hello_acp](00_sync/000_hello_acp/)