diff --git a/README.md b/README.md index c2553e3..6f5272c 100644 --- a/README.md +++ b/README.md @@ -98,9 +98,9 @@ This configuration file specifies basic metadata (name, framework, version), def } ``` -## Local Deployment +## Local Development -Deploy and test your agents locally with full debugging capabilities. +Deploy and test your agents locally with full debugging capabilities before deploying to RunAgent Cloud. ### Deploy Agent Locally @@ -115,6 +115,20 @@ This starts a local FastAPI server with: - WebSocket support for streaming - Built-in API documentation at `/docs` +### Deploy to RunAgent Cloud + +Once your agent is tested locally, deploy to production: + +```bash +# Authenticate (first time only) +runagent setup --api-key + +# Deploy to cloud +runagent deploy --folder . +``` + +Your agent will be live globally with automatic scaling, monitoring, and enterprise security. View all your agents and execution metrics in the [dashboard](https://app.run-agent.ai/dashboard). + ## **LangGraph Problem Solver Agent (An Example)** @@ -334,28 +348,52 @@ func main() { --- -## Action Memory System (Coming Soon) +
-RunAgent is introducing **Action Memory** - a revolutionary approach to agent reliability that focuses on *how to remember* rather than *what to remember*. +## πŸš€ RunAgent Cloud Deployment -### How It Will Work +**Now Available: Production-Ready Cloud Infrastructure** -- **Action-Centric**: Instead of storing raw conversation data, it captures decision patterns and successful action sequences -- **Cross-Language**: Memory persists across all SDK languages seamlessly -- **Reliability Focus**: Learns from successful outcomes to improve future decisions -- **Ecosystem Integration**: Works with any framework - LangGraph, CrewAI, Letta, and more +Deploy to production in seconds with enterprise-grade infrastructure -This will ensure your agents become more reliable over time, regardless of which programming language or framework you use to interact with them. +
---- + + + + + + +
+Sign Up + +Dashboard + +Documentation +
+ +
+ +Deploy your agents to RunAgent Cloud with enterprise-grade infrastructure and experience the fastest agent deployment. RunAgent Cloud provides serverless auto-scaling, comprehensive security, and real-time monitoring - all managed for you. + +### Get Started with RunAgent Cloud -## Remote Deployment (Coming very soon) +1. **Sign up** at [app.run-agent.ai](https://app.run-agent.ai/auth/signin) +2. **Generate API Key**: After signing in, go to **Settings β†’ API Keys β†’ Generate API Key** +3. **Authenticate CLI**: Configure your CLI with your API key +4. **Deploy**: Deploy your agents with a single command -Deploy your agents with enterprise-grade infrastructure and experience the fastest agent deployment. +```bash +# Authenticate with RunAgent Cloud +runagent setup --api-key + +# Deploy your agent +runagent deploy --folder ./my-agent +``` -### ⚑Fastest agent deployment +### Fastest Agent Deployment -From zero to production in the time it takes to draw a breath, making **RunAgent** one of the fastest agent deployment platforms available on planet earth 🌍 . +From zero to production in seconds. RunAgent Cloud automatically selects the optimal VM image based on your agent's requirements, with deployment typically completing in 30-60 seconds for standard images, or up to 2 minutes for specialized configurations. ### Security-First Architecture @@ -365,24 +403,55 @@ Every agent runs in its own **isolated sandbox environment**: - Resource limits and monitoring - Zero data leakage between agents -### ✨ The +++999 Aura of Agent Deployment +### Dashboard & Monitoring -Our remote deployment will provide: +The RunAgent Cloud dashboard provides comprehensive insights into your agents: -- Auto-scaling based on demand -- Global edge distribution -- Built-in monitoring and analytics -- Production-grade security and compliance +- **Agent Execution Metadata** - Detailed information about each execution +- **Execution Time Tracking** - Monitor performance and optimize accordingly +- **Agent Management** - View and manage all your deployed agents +- **Usage Analytics** - Track usage patterns and resource consumption +- **Real-time Monitoring** - Live status and health checks +- **Execution History** - Complete audit trail of all agent invocations +Access your dashboard at [app.run-agent.ai/dashboard](https://app.run-agent.ai/dashboard) after signing in. +### Enterprise-Grade Features -## Documentation +RunAgent Cloud provides: + +- **Auto-scaling** - Automatically scales based on demand +- **Global Edge Distribution** - Low-latency access worldwide +- **Built-in Monitoring** - Comprehensive analytics and observability +- **Production-Grade Security** - Enterprise security and compliance +- **Multiple VM Images** - Automatic image selection optimized for your agent +- **Serverless Infrastructure** - Zero infrastructure management + +--- + +## πŸ“š Documentation - **[Getting Started](https://docs.run-agent.ai/get-started/introduction.md)** - Deploy your first agent in 5 minutes - **[CLI Reference](https://docs.run-agent.ai/cli/overview.md)** - Complete command-line interface guide - **[SDK Documentation](https://docs.run-agent.ai/sdk/overview.md)** - Multi-language SDK guides - **[Framework Guides](https://docs.run-agent.ai/frameworks/overview.md)** - Framework-specific tutorials - **[API Reference](https://docs.run-agent.ai/api-reference/introduction.md)** - REST API documentation +- **[RunAgent Cloud Guide](https://docs.run-agent.ai/runagent-cloud/overview)** - Complete cloud deployment guide + +--- + +## 🧠 Action Memory System (Coming Soon) + +RunAgent is introducing **Action Memory** - a revolutionary approach to agent reliability that focuses on *how to remember* rather than *what to remember*. + +### How It Will Work + +- **Action-Centric**: Instead of storing raw conversation data, it captures decision patterns and successful action sequences +- **Cross-Language**: Memory persists across all SDK languages seamlessly +- **Reliability Focus**: Learns from successful outcomes to improve future decisions +- **Ecosystem Integration**: Works with any framework - LangGraph, CrewAI, Letta, and more + +This will ensure your agents become more reliable over time, regardless of which programming language or framework you use to interact with them. --- diff --git a/docs/api-reference/endpoints/health.mdx b/docs/api-reference/endpoints/health.mdx index d1c890d..4176d23 100644 --- a/docs/api-reference/endpoints/health.mdx +++ b/docs/api-reference/endpoints/health.mdx @@ -203,6 +203,6 @@ def update_metrics(agent_id): ## See Also -- [Monitoring Guide](/deployment/cloud-deployment#monitoring) - Full monitoring setup +- [Monitoring Guide](/runagent-cloud/cloud-deployment#monitoring) - Full monitoring setup - [Status Endpoint](/api-reference/endpoints/get-agent) - Detailed agent info - [Metrics API](/api-reference/webhooks) - Metrics collection \ No newline at end of file diff --git a/docs/configuration/environment.mdx b/docs/configuration/environment.mdx index fdb9377..ed371c8 100644 --- a/docs/configuration/environment.mdx +++ b/docs/configuration/environment.mdx @@ -294,5 +294,5 @@ for key, value in os.environ.items(): ## See Also - [Configuration File](/configuration/config-file) - Config structure -- [Security Best Practices](/deployment/cloud-deployment) - Production security +- [Security Best Practices](/runagent-cloud/cloud-deployment) - Production security - [Local Development](/deployment/local-development) - Development setup \ No newline at end of file diff --git a/docs/deployment/cloud-deployment.mdx b/docs/deployment/cloud-deployment.mdx index bf52cb7..6a058a5 100644 --- a/docs/deployment/cloud-deployment.mdx +++ b/docs/deployment/cloud-deployment.mdx @@ -131,17 +131,94 @@ Starting agent: abc-123-def-456 🌐 Endpoint: https://api.run-agent.ai/api/v1/agents/abc-123-def-456/execute ``` +## Agent Configuration + +### Agent ID and Entrypoints + +When you initialize a new agent with `runagent init`, it automatically: +1. **Generates a unique agent ID** and adds it to `runagent.config.json` +2. **Creates a basic configuration** with framework and template settings + +**Important:** You must add your entrypoints to the configuration file before deploying. + +#### Using `runagent init` (Recommended) + +```bash +# Initialize a new agent +runagent init my-agent --framework langgraph + +# This creates runagent.config.json with: +# - Generated agent_id +# - Framework configuration +# - Empty entrypoints array (you need to add these) +``` + +**Example `runagent.config.json` after init:** +```json +{ + "agent_name": "my-agent", + "agent_id": "abc-123-def-456", + "version": "1.0.0", + "framework": "langgraph", + "agent_architecture": { + "entrypoints": [] // ← You need to add entrypoints here + } +} +``` + +**Add your entrypoints:** +```json +{ + "agent_name": "my-agent", + "agent_id": "abc-123-def-456", + "version": "1.0.0", + "framework": "langgraph", + "agent_architecture": { + "entrypoints": [ + { + "tag": "chat", + "file": "main.py", + "module": "chat_agent" + }, + { + "tag": "chat_stream", + "file": "main.py", + "module": "chat_agent_stream" + } + ] + } +} +``` + +#### Manually Editing Agent ID + +If you manually edit the `agent_id` in `runagent.config.json`, you **must register** the agent: + +```bash +# Register the agent after manually editing agent_id +runagent register . + +# Or use the config command +runagent config --register-agent . +``` + + +**Important:** If you manually change the `agent_id` in your config file, RunAgent won't recognize it until you register it. Always run `runagent register .` after manually editing the agent ID. + + ## Agent Validation Before upload, RunAgent validates your agent: ### Required Files -- `runagent.config.json` - Agent configuration +- `runagent.config.json` - Agent configuration with valid `agent_id` and `entrypoints` - `main.py` or `agent.py` - Entry point file - `requirements.txt` - Python dependencies (optional) ### Validation Checks - βœ… Configuration file exists and is valid JSON +- βœ… Agent ID exists in configuration +- βœ… Agent ID is registered (if manually edited) - βœ… Entry point file exists - βœ… Entrypoints are properly defined - βœ… Framework is supported @@ -151,15 +228,18 @@ Before upload, RunAgent validates your agent: ```json { "agent_name": "my-agent", + "agent_id": "abc-123-def-456", "version": "1.0.0", "framework": "langgraph", - "entrypoints": [ - { - "tag": "chat", - "file": "main.py", - "module": "agent.chat" - } - ] + "agent_architecture": { + "entrypoints": [ + { + "tag": "chat", + "file": "main.py", + "module": "agent.chat" + } + ] + } } ``` @@ -236,10 +316,17 @@ runagent run --id --tag --input config.json For streaming entrypoints (must end with `_stream`): ```bash -# Run streaming endpoint -runagent run --id --tag chat_stream --message="Tell me a story" +# Run streaming endpoint using run-stream command +runagent run-stream --id --tag chat_stream --message="Tell me a story" + +# Or with local agent +runagent run-stream --id --tag chat_stream --local --message="Tell me a story" ``` + +**Important:** Use `runagent run-stream` (not `runagent run`) for streaming execution. The `run-stream` command uses WebSocket connections for real-time streaming. + + ## Cloud vs Local Deployment | Feature | Local | Cloud | @@ -262,16 +349,22 @@ runagent run --id --tag chat_stream --message="Tell me a story" runagent init my-agent --framework langgraph --template default cd my-agent -# 2. Test locally +# 2. Add entrypoints to runagent.config.json +# Edit the file and add your entrypoints to agent_architecture.entrypoints + +# 3. If you manually edited agent_id, register it +runagent register . + +# 4. Test locally runagent serve -# 3. Authenticate (if not already done) +# 5. Authenticate (if not already done) runagent setup --api-key -# 4. Deploy to cloud +# 6. Deploy to cloud runagent deploy --folder . -# 5. Test cloud deployment +# 7. Test cloud deployment runagent run --id --tag chat --message="Hello" ``` diff --git a/docs/deployment/local-development.mdx b/docs/deployment/local-development.mdx index 8f23a14..e028832 100644 --- a/docs/deployment/local-development.mdx +++ b/docs/deployment/local-development.mdx @@ -370,6 +370,6 @@ runagent serve . ## See Also -- [Cloud Deployment](/deployment/cloud-deployment) - Deploy to production +- [Cloud Deployment](/runagent-cloud/cloud-deployment) - Deploy to production - [CLI Reference](/cli/overview) - Complete CLI documentation - [Troubleshooting](/resources/troubleshooting) - Common issues \ No newline at end of file diff --git a/docs/docs.json b/docs/docs.json index 0f69864..71063f5 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -93,8 +93,7 @@ { "group": "Deployment", "pages": [ - "deployment/local-development", - "deployment/cloud-deployment" + "deployment/local-development" ] }, { @@ -105,6 +104,18 @@ } ] }, + { + "tab": "RunAgent Cloud", + "groups": [ + { + "group": "RunAgent Cloud", + "pages": [ + "runagent-cloud/overview", + "runagent-cloud/cloud-deployment" + ] + } + ] + }, { "tab": "Reference", "groups": [ diff --git a/docs/explanation/architecture-overview.mdx b/docs/explanation/architecture-overview.mdx index e333fb6..a751153 100644 --- a/docs/explanation/architecture-overview.mdx +++ b/docs/explanation/architecture-overview.mdx @@ -482,7 +482,7 @@ graph TB Learn advanced performance optimization techniques - + Deploy your agents to production diff --git a/docs/explanation/installation.mdx b/docs/explanation/installation.mdx index 8625a9a..960c509 100644 --- a/docs/explanation/installation.mdx +++ b/docs/explanation/installation.mdx @@ -31,10 +31,28 @@ RunAgent provides Python, JavaScript, Rust, and Go SDKs along with a powerful CL runagent --version ``` - - For cloud deployment features (coming soon), login to get your API key: + + For cloud deployment and middleware sync features, configure your authentication: ```bash - runagent login + runagent setup + ``` + + This will prompt you to choose between: + - **Express Setup (Browser login)**: Opens your browser for secure authentication + - **Manual Setup**: Enter your API key directly + + + **Express Setup** uses device code authentication - you'll get a code to enter in your browser, and the CLI will automatically complete the setup once you authenticate. + + + To view your current configuration: + ```bash + runagent whoami + ``` + + To reconfigure: + ```bash + runagent setup --again ``` diff --git a/docs/explanation/introduction.mdx b/docs/explanation/introduction.mdx index 5debaee..72159ca 100644 --- a/docs/explanation/introduction.mdx +++ b/docs/explanation/introduction.mdx @@ -77,39 +77,66 @@ The fastest way to experience the magic is with **RunAgent CLI**: cd my_agent ``` - This creates a new directory with the basic structure you need to get started. - - - + This creates a new directory with everything you need to get started: - In your agent codebase (for example, `main.py`), define a function that will serve as your agent's entrypoint: - - ```python main.py -def mock_response(message, role="user"): - """Test the mock agent with non-streaming responses""" - # Your agent logic here - # Process the message and generate a response - return response.content + ``` + my_agent/ + β”œβ”€β”€ main.py # Your agent's functions (already defined!) + β”œβ”€β”€ runagent.config.json # Entrypoints already configured! + └── requirements.txt # Dependencies ``` - This `mock_response` function is one of the invocation functions for our agent. It takes a message and role as parameters and returns the agent's response. - - - + + **What `runagent init` created for you:** + - A `main.py` file with example agent functions (`mock_response` and `mock_response_stream`) + - A `runagent.config.json` file with entrypoints already configured + - All the boilerplate needed to make your Python agent accessible from any language + - Open the `runagent.config.json` file and add your function as an entrypoint: + The `runagent.config.json` file contains all the configuration for your agent, including: ```json -"entrypoints": [ - { - "file": "main.py", - "module": "mock_response", - "tag": "minimal" - } -] + { + "agent_name": "my_agent", + "description": "My AI agent", + "framework": "default", + "template": "default", + "version": "1.0.0", + "created_at": "2025-01-15T10:30:00", + "agent_id": "f7066c98-0eb2-488c-bb37-a869a93d51ce", + "template_source": { + "repo_url": "https://github.com/runagent-dev/runagent.git", + "author": "runagent-cli", + "path": "templates/default/default" + }, + "agent_architecture": { + "entrypoints": [ + { + "file": "main.py", + "module": "mock_response", + "tag": "minimal" + }, + { + "file": "main.py", + "module": "mock_response_stream", + "tag": "minimal_stream" + } + ] + }, + "auth_settings": { + "type": "none" + }, + "env_vars": {} + } ``` - The `file` specifies where your function lives, `module` is the function name, and `tag` is a label you'll use to call this specific entrypoint. + + **Key fields:** + - `agent_id`: A unique identifier for your agent (generated automatically) + - `agent_architecture.entrypoints`: Defines which Python functions are accessible as API endpoints + - `auth_settings`: Authentication configuration (defaults to "none") + - `env_vars`: Environment variables for your agent + @@ -295,7 +322,7 @@ The same code you tested locally now runs in a fully managed production environm Explore advanced deployment options, environment variables, and monitoring capabilities. @@ -404,9 +431,9 @@ When your entrypoint streams a response, RunAgent makes it feel native in every - + - Create a function in your agent codebase that returns an Iterator (in this case in `main.py`): + When you ran `runagent init`, it automatically created both a non-streaming and a streaming function for you. The streaming function is already defined in `main.py` and configured in `runagent.config.json`: ```python main.py def mock_response_stream(message, role="user") -> Iterator[str]: @@ -417,29 +444,14 @@ def mock_response_stream(message, role="user") -> Iterator[str]: yield chunk ``` - This `mock_response_stream` function will return an Iterator that yields response chunks as they're generated. - - - - - Add this function to your `runagent.config.json` file as another entrypoint: - - ```json -"entrypoints": [ - { - "file": "main.py", - "module": "mock_response_stream", - "tag": "minimal_stream" - } -] - ``` + The `runagent.config.json` already includes this entrypoint with the tag `minimal_stream` (note the `_stream` suffix, which tells RunAgent this is a streaming endpoint). The tag for a streaming entrypoint must end with a `_stream` suffix. This is how RunAgent identifies it as a streaming endpoint. - Spin up the agent just like before. Now you have an additional streaming entrypoint available. + Start your agent locally (the streaming endpoint is already available): ```bash runagent serve . diff --git a/docs/explanation/overview.mdx b/docs/explanation/overview.mdx index 89223c4..ba77902 100644 --- a/docs/explanation/overview.mdx +++ b/docs/explanation/overview.mdx @@ -6,20 +6,109 @@ icon: 'lightbulb' import NeedHelp from '/snippets/need-help.mdx'; -Short, diagram-first pages that explain how RunAgent works and why. - - - - - - - - - - +> Understanding the "why" and "how" behind RunAgent. These pages explain the concepts, architecture, and design decisions that make RunAgent work. + +## What's in This Section? + +The Explanation section contains **theory-first, diagram-rich pages** that dive deep into how RunAgent works. Unlike tutorials (which show you how to do things) or how-tos (which solve specific problems), these pages explain the underlying concepts and architecture. -Keep theory here. Tutorials/how-tos should only include brief callouts. +**Keep theory here.** Tutorials and how-tos should only include brief callouts. This section is for deep dives into concepts and architecture. +## Start Here + + + + Understand the problems RunAgent solves and why it exists + + + Quick cheat sheet of core concepts in one page + + + High-level overview of RunAgent's capabilities and benefits + + + +## Core Concepts & Architecture + + + + **Entrypoints, tags, agent lifecycle, and more.** Understand the fundamental building blocks that make RunAgent work. + + + **How RunAgent works under the hood.** Learn about the system architecture, request flow, and component interactions. + + + **Framework integration patterns.** See how RunAgent works with LangGraph, CrewAI, and other AI frameworks. + + + **What RunAgent can do today.** A comprehensive map of current capabilities and upcoming features. + + + +## Production & Operations + + + + **Deploying to production.** Scaling, monitoring, error handling, and best practices for production deployments. + + + **Security architecture and best practices.** Learn about sandboxing, authentication, and securing your agents. + + + +## Project Information + + + + **What's new and what changed.** Track updates, new features, and breaking changes. + + + **What's coming next.** See planned features, improvements, and the future direction of RunAgent. + + + +## Vision & Future + + + + **The future of agent coordination.** How agents will communicate and collaborate with each other. + + + +## How to Use This Section + + + + Start with **[Why RunAgent?](./why-runagent)** to understand the problems it solves, then read **[Key Concepts at a Glance](./key-concepts-at-a-glance)** for a quick overview. After that, dive into **[Core Concepts](./core-concepts)** for detailed explanations. + + + + Read **[Production Considerations](./production-considerations)** for scaling and monitoring guidance, and **[Security Model](./security)** for security best practices. + + + + Check **[Frameworks Overview](./frameworks-overview)** to see how RunAgent integrates with LangGraph, CrewAI, and other frameworks. + + + + **[Architecture Overview](./architecture-overview)** explains how RunAgent works internally, including request flow, component interactions, and system design. + + + +## Related Sections + + + + Step-by-step guides to build real applications + + + Solutions to specific problems and use cases + + + API documentation and SDK references + + + diff --git a/docs/explanation/production-considerations.mdx b/docs/explanation/production-considerations.mdx index d1c2bd5..331fbfd 100644 --- a/docs/explanation/production-considerations.mdx +++ b/docs/explanation/production-considerations.mdx @@ -630,7 +630,7 @@ async def health_check() -> Dict[str, Any]: Learn about RunAgent's security model - + Deploy your agents to the cloud diff --git a/docs/explanation/quickstart-map.mdx b/docs/explanation/quickstart-map.mdx index 4cb88de..67e1b19 100644 --- a/docs/explanation/quickstart-map.mdx +++ b/docs/explanation/quickstart-map.mdx @@ -45,7 +45,7 @@ icon: 'map' **Then explore:** - [Framework integrations](/how-to/frameworks/langgraph) - [Testing agents](/how-to/advanced-tasks) - - [Production deployment](/deployment/cloud-deployment) + - [Production deployment](/runagent-cloud/cloud-deployment) @@ -79,7 +79,7 @@ icon: 'map' - [Security model](/explanation/security) (10 min) **Then explore:** - - [Cloud deployment](/deployment/cloud-deployment) + - [Cloud deployment](/runagent-cloud/cloud-deployment) - [CI/CD integration](/how-to/advanced-tasks) - [Observability](/how-to/advanced-tasks) @@ -148,7 +148,7 @@ icon: 'map' 1. [Architecture overview](/explanation/architecture-overview) (15 min) 2. [Production considerations](/explanation/production-considerations) (10 min) 3. [Security model](/explanation/security) (10 min) - 4. [Cloud deployment](/deployment/cloud-deployment) (30 min) + 4. [Cloud deployment](/runagent-cloud/cloud-deployment) (30 min) **Focus on:** - Production readiness @@ -174,7 +174,7 @@ icon: 'map' **Quick fix**: Check language-specific guides - **Go to**: [Cloud deployment](/deployment/cloud-deployment) + **Go to**: [Cloud deployment](/runagent-cloud/cloud-deployment) **Or**: [Production considerations](/explanation/production-considerations) **Quick fix**: Check [Advanced tasks](/how-to/advanced-tasks) diff --git a/docs/how-to/advanced-tasks.mdx b/docs/how-to/advanced-tasks.mdx index f0c4eeb..3c78195 100644 --- a/docs/how-to/advanced-tasks.mdx +++ b/docs/how-to/advanced-tasks.mdx @@ -8,12 +8,15 @@ icon: 'cog' This section covers advanced patterns and techniques for building production-ready agents with RunAgent. +## Available Guides + +- **[Streaming Responses](/how-to/advanced/streaming-responses)** - Real-time streaming patterns and optimization + ## Coming Soon -Advanced task guides are being developed and will include: +Additional advanced task guides are being developed: - **Testing agents** - Unit testing, integration testing, and mocking -- **Streaming responses** - Advanced streaming patterns and optimization - **Observability** - Logging, monitoring, and debugging deployed agents - **Security** - Authentication, authorization, and data protection - **CI/CD** - Automated deployment and testing pipelines diff --git a/docs/how-to/advanced/streaming-responses.mdx b/docs/how-to/advanced/streaming-responses.mdx new file mode 100644 index 0000000..e7e81fd --- /dev/null +++ b/docs/how-to/advanced/streaming-responses.mdx @@ -0,0 +1,477 @@ +--- +title: 'Streaming Responses' +description: 'Use streaming entrypoints for real-time agent responses' +icon: 'stream' +--- + +import NeedHelp from '/snippets/need-help.mdx'; + + + **Prerequisites**: Completed [Deploy Your First Agent](/tutorials/deploy-your-first-agent) tutorial and understand [Core Concepts](/explanation/core-concepts) + + +## Overview + +Streaming responses allow you to receive agent output in real-time as it's generated, rather than waiting for the complete response. This provides better user experience for long-running operations, chat interfaces, and interactive applications. + +## Key Concepts + +### Streaming vs Synchronous + +| Feature | Synchronous | Streaming | +|---------|------------|-----------| +| **Command** | `runagent run` | `runagent run-stream` | +| **Connection** | REST API | WebSocket | +| **Response** | Complete result at once | Real-time chunks | +| **Tag Requirement** | Any tag | Must end with `_stream` | +| **Use Case** | Quick operations | Long-running, interactive | + +### Entrypoint Naming Convention + +Streaming entrypoints **must** end with `_stream`: + +```python +# Synchronous entrypoint +def chat_agent(message: str) -> str: + return "Complete response" + +# Streaming entrypoint (note the _stream suffix) +def chat_agent_stream(message: str) -> Iterator[str]: + yield "Response " + yield "chunk " + yield "by " + yield "chunk" +``` + +## Using CLI for Streaming + +### Basic Streaming Command + +```bash +# Stream from cloud agent +runagent run-stream --id --tag chat_stream --message="Tell me a story" + +# Stream from local agent +runagent run-stream --id --tag chat_stream --local --message="Tell me a story" +``` + +### Command Options + +| Option | Description | Required | +|--------|-------------|----------| +| `--id` | Agent ID to run | Yes (or use --host/--port) | +| `--tag` | Entrypoint tag (must end with `_stream`) | Yes | +| `--local` | Use local agent instead of cloud | No | +| `--host` | Host address (use with --port) | No | +| `--port` | Port number (use with --host) | No | +| `--input` | Path to JSON input file | No | +| `--timeout` | Timeout in seconds | No | + +### Examples + +#### Example 1: Basic Streaming + +```bash +# Stream a story generation +runagent run-stream \ + --id abc-123-def-456 \ + --tag story_stream \ + --prompt="Write a short story about a robot" +``` + +#### Example 2: Using Input File + +Create `input.json`: +```json +{ + "query": "Explain quantum computing", + "detail_level": "beginner" +} +``` + +```bash +# Stream with input file +runagent run-stream \ + --id abc-123-def-456 \ + --tag explain_stream \ + --input input.json +``` + +#### Example 3: Local Agent Streaming + +```bash +# Stream from locally running agent +runagent run-stream \ + --id local-agent-123 \ + --tag chat_stream \ + --local \ + --message="Hello, how are you?" +``` + +#### Example 4: With Host and Port + +```bash +# Stream from custom host/port +runagent run-stream \ + --host localhost \ + --port 8080 \ + --tag chat_stream \ + --message="Test message" +``` + +## Using SDKs for Streaming + +### Python SDK + +```python +from runagent import RunAgentClient + +# Connect to streaming entrypoint +client = RunAgentClient( + agent_id="your_agent_id", + entrypoint_tag="chat_stream", # Must end with _stream + local=False # Set to True for local agents +) + +# Stream responses +for chunk in client.run(message="Tell me a story"): + print(chunk, end="", flush=True) +``` + +### JavaScript/TypeScript SDK + +```javascript +const { RunAgentClient } = require('runagent'); + +async function streamResponse() { + const client = new RunAgentClient({ + agentId: 'your_agent_id', + entrypointTag: 'chat_stream', // Must end with _stream + local: false + }); + + await client.initialize(); + + const stream = await client.run({ + message: 'Tell me a story' + }); + + for await (const chunk of stream) { + process.stdout.write(chunk); + } +} + +streamResponse(); +``` + +### Go SDK + +```go +package main + +import ( + "context" + "fmt" + "github.com/runagent-dev/runagent-go/pkg/client" +) + +func main() { + ctx := context.Background() + + c, err := client.NewWithAddress( + "your_agent_id", + "chat_stream", // Must end with _stream + false, + "localhost", + 8451, + ) + if err != nil { + log.Fatal(err) + } + defer c.Close() + + s, err := c.RunStream(ctx, map[string]interface{}{ + "message": "Tell me a story", + }) + if err != nil { + log.Fatal(err) + } + defer s.Close() + + for { + data, hasMore, err := s.Next(ctx) + if err != nil { + log.Fatal(err) + } + if !hasMore { + break + } + fmt.Print(data) + } +} +``` + +### Rust SDK + +```rust +use runagent::client::RunAgentClient; +use serde_json::json; +use futures::StreamExt; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = RunAgentClient::new( + "your_agent_id", + "chat_stream", // Must end with _stream + false + ).await?; + + let mut stream = client.run_stream(&[ + ("message", json!("Tell me a story")) + ]).await?; + + while let Some(chunk) = stream.next().await { + print!("{}", chunk?); + } + + Ok(()) +} +``` + +## Creating Streaming Entrypoints + +### Python Streaming Function + +```python +from typing import Iterator + +def chat_stream(message: str, user_id: str = "anonymous") -> Iterator[str]: + """ + Streaming chat agent that yields response chunks. + + Note: Function name ends with _stream, and return type is Iterator[str] + """ + response_parts = [ + "Hello ", + user_id, + "! ", + "You said: ", + message, + ". ", + "Let me think about that...\n", + "Here's my response: ", + generate_response(message) + ] + + for part in response_parts: + yield part + # Simulate processing delay + import time + time.sleep(0.1) +``` + +### Configuration + +Add to `runagent.config.json`: + +```json +{ + "agent_architecture": { + "entrypoints": [ + { + "file": "main.py", + "module": "chat_stream", + "tag": "chat_stream" + } + ] + } +} +``` + + +**Important:** The entrypoint tag must end with `_stream` for streaming to work. The CLI command `run-stream` validates this requirement. + + +## Best Practices + +### 1. Use Streaming for Long Operations + +Streaming is ideal for: +- **Long text generation** (stories, articles, explanations) +- **Interactive chat** (real-time conversation) +- **Progress updates** (status messages during processing) +- **Large data processing** (streaming results as they're computed) + +### 2. Chunk Size Considerations + +```python +# Good: Reasonable chunk sizes +def good_stream() -> Iterator[str]: + yield "Processing step 1...\n" + yield "Processing step 2...\n" + yield "Final result: " + result + +# Avoid: Too small chunks (overhead) +def bad_stream() -> Iterator[str]: + for char in very_long_string: + yield char # Too granular +``` + +### 3. Error Handling in Streaming + +```python +from typing import Iterator + +def robust_stream(query: str) -> Iterator[str]: + try: + yield "Starting processing...\n" + + # Your processing logic + for result in process_query(query): + yield result + "\n" + + yield "Processing complete!\n" + except Exception as e: + yield f"\nError occurred: {str(e)}\n" + raise +``` + +### 4. Client-Side Error Handling + +```python +from runagent import RunAgentClient, RunAgentError + +client = RunAgentClient( + agent_id="your_agent_id", + entrypoint_tag="chat_stream", + local=False +) + +try: + for chunk in client.run(message="Hello"): + print(chunk, end="", flush=True) +except RunAgentError as e: + print(f"\nStreaming error: {e}") +except KeyboardInterrupt: + print("\n\nStreaming interrupted by user") +``` + +## Troubleshooting + +### Error: Tag must end with `_stream` + +**Problem:** +``` +❌ Execution failed: Streaming command requires entrypoint tag ending with '_stream'. Got: chat +``` + +**Solution:** +- Ensure your entrypoint tag ends with `_stream` +- Check your `runagent.config.json` configuration +- Use the correct tag: `chat_stream` instead of `chat` + +### Error: Connection timeout + +**Problem:** WebSocket connection times out during streaming + +**Solution:** +```bash +# Increase timeout +runagent run-stream --id --tag chat_stream --timeout 300 --message="..." +``` + +### Streaming stops unexpectedly + +**Problem:** Stream ends without completing + +**Possible causes:** +- Agent function raised an exception +- Network connection interrupted +- Agent timeout exceeded + +**Solution:** +- Check agent logs: `runagent db logs --agent-id ` +- Verify agent function handles errors gracefully +- Test with shorter inputs first + +### No output appears + +**Problem:** Command runs but no output + +**Solution:** +- Verify entrypoint is actually streaming (yields chunks) +- Check agent is running: `runagent db status --agent-id ` +- Test with synchronous version first to verify agent works + +## Performance Considerations + +### WebSocket Overhead + +Streaming uses WebSocket connections which have: +- **Lower latency** for real-time updates +- **Persistent connection** overhead +- **Better for long-running** operations + +### When to Use Streaming + +βœ… **Use streaming when:** +- Response time > 2 seconds +- User needs real-time feedback +- Generating long-form content +- Interactive applications + +❌ **Avoid streaming when:** +- Quick responses (< 1 second) +- Simple data retrieval +- Batch processing (use async instead) + +## Advanced Patterns + +### Progressive Response Building + +```python +def smart_stream(query: str) -> Iterator[str]: + # Initial acknowledgment + yield "πŸ” Analyzing your query...\n\n" + + # Progressive results + yield "πŸ“Š Found relevant information:\n" + for item in search_results: + yield f" β€’ {item}\n" + + # Final summary + yield "\nβœ… Analysis complete!" +``` + +### Conditional Streaming + +```python +def conditional_stream(query: str, stream: bool = True) -> Iterator[str]: + if stream: + # Streaming mode + for chunk in process_streaming(query): + yield chunk + else: + # Non-streaming: yield complete result + result = process_complete(query) + yield result +``` + +## Next Steps + + + + Learn more about SDK streaming capabilities + + + Understand entrypoints and streaming architecture + + + Best practices for production streaming + + + Complete CLI command reference + + + + diff --git a/docs/how-to/call-from-go.mdx b/docs/how-to/call-from-go.mdx index ae28901..a277627 100644 --- a/docs/how-to/call-from-go.mdx +++ b/docs/how-to/call-from-go.mdx @@ -1170,7 +1170,7 @@ func TestAgentStreaming(t *testing.T) { Learn advanced concurrency patterns for Go - + Deploy your Go applications to production diff --git a/docs/how-to/call-from-javascript.mdx b/docs/how-to/call-from-javascript.mdx index 4631d23..de200aa 100644 --- a/docs/how-to/call-from-javascript.mdx +++ b/docs/how-to/call-from-javascript.mdx @@ -708,7 +708,7 @@ describe('Agent Integration', () => { Learn advanced async patterns for JavaScript - + Deploy your JavaScript applications to production diff --git a/docs/how-to/call-from-python.mdx b/docs/how-to/call-from-python.mdx index 0e1b1cb..0f6f591 100644 --- a/docs/how-to/call-from-python.mdx +++ b/docs/how-to/call-from-python.mdx @@ -579,7 +579,7 @@ def test_agent_streaming(agent_client): Learn advanced async patterns for Python - + Deploy your Python applications to production diff --git a/docs/how-to/call-from-rust.mdx b/docs/how-to/call-from-rust.mdx index 934d6fc..587516a 100644 --- a/docs/how-to/call-from-rust.mdx +++ b/docs/how-to/call-from-rust.mdx @@ -885,7 +885,7 @@ async fn test_agent_streaming() { Continue your journey with RunAgent: - **[Async Patterns](/how-to/advanced-tasks)** - Learn advanced async patterns for Rust -- **[Production Deployment](/how-to/deployment/cloud-deployment)** - Deploy your Rust applications to production +- **[Production Deployment](/runagent-cloud/cloud-deployment)** - Deploy your Rust applications to production - **[Multi-Language Integration](/tutorials/multi-language-wrapper)** - Integrate with other programming languages - **[Performance Tuning](/explanation/production-considerations)** - Optimize your Rust applications diff --git a/docs/how-to/frameworks/ag2.mdx b/docs/how-to/frameworks/ag2.mdx index b33b2da..a612ec2 100644 --- a/docs/how-to/frameworks/ag2.mdx +++ b/docs/how-to/frameworks/ag2.mdx @@ -728,7 +728,7 @@ def invoke_cached(message, max_turns): ## Next Steps - **[Advanced Patterns](/how-to/advanced-tasks)** - Learn advanced AG2 patterns -- **[Production Deployment](/how-to/deployment/cloud-deployment)** - Deploy to production +- **[Production Deployment](/runagent-cloud/cloud-deployment)** - Deploy to production - **[Multi-Language Access](/tutorials/multi-language-wrapper)** - Access from different languages - **[Performance Tuning](/explanation/production-considerations)** - Optimize for production diff --git a/docs/how-to/frameworks/agno.mdx b/docs/how-to/frameworks/agno.mdx index 94f9e40..548f464 100644 --- a/docs/how-to/frameworks/agno.mdx +++ b/docs/how-to/frameworks/agno.mdx @@ -515,7 +515,7 @@ def debug_agno_agent(message: str, user_id: str) -> Dict[str, Any]: Learn advanced Agno patterns and techniques - + Deploy your Agno agents to production diff --git a/docs/how-to/frameworks/crewai.mdx b/docs/how-to/frameworks/crewai.mdx index fe18fcf..385c2a6 100644 --- a/docs/how-to/frameworks/crewai.mdx +++ b/docs/how-to/frameworks/crewai.mdx @@ -568,7 +568,7 @@ def debug_crew(topic: str) -> Dict[str, Any]: Learn advanced CrewAI patterns and techniques - + Deploy your CrewAI system to production diff --git a/docs/how-to/frameworks/custom.mdx b/docs/how-to/frameworks/custom.mdx index e51e30e..b38e6fc 100644 --- a/docs/how-to/frameworks/custom.mdx +++ b/docs/how-to/frameworks/custom.mdx @@ -527,7 +527,7 @@ def debug_custom_agent(request: str, context: Dict[str, Any] = None) -> Dict[str Learn advanced custom agent patterns and techniques - + Deploy your custom agents to production diff --git a/docs/how-to/frameworks/langgraph.mdx b/docs/how-to/frameworks/langgraph.mdx index 7531bff..0da1b3c 100644 --- a/docs/how-to/frameworks/langgraph.mdx +++ b/docs/how-to/frameworks/langgraph.mdx @@ -531,7 +531,7 @@ workflow.add_node("debug", debug_node) Learn advanced LangGraph patterns and techniques - + Deploy your LangGraph agent to production diff --git a/docs/how-to/frameworks/letta.mdx b/docs/how-to/frameworks/letta.mdx index d1f4e37..54ebcf2 100644 --- a/docs/how-to/frameworks/letta.mdx +++ b/docs/how-to/frameworks/letta.mdx @@ -735,7 +735,7 @@ finally: ## Next Steps - **[Advanced Patterns](/how-to/advanced-tasks)** - Learn advanced Letta patterns -- **[Production Deployment](/how-to/deployment/cloud-deployment)** - Deploy to production +- **[Production Deployment](/runagent-cloud/cloud-deployment)** - Deploy to production - **[Multi-Language Access](/tutorials/multi-language-wrapper)** - Access from different languages - **[Performance Tuning](/explanation/production-considerations)** - Optimize for production diff --git a/docs/how-to/frameworks/llamaindex.mdx b/docs/how-to/frameworks/llamaindex.mdx index 0cf739a..04e709b 100644 --- a/docs/how-to/frameworks/llamaindex.mdx +++ b/docs/how-to/frameworks/llamaindex.mdx @@ -1074,7 +1074,7 @@ response = await agent.achat(query) # Good ## Next Steps - **[Advanced Patterns](/how-to/advanced-tasks)** - Learn advanced LlamaIndex patterns -- **[Production Deployment](/how-to/deployment/cloud-deployment)** - Deploy to production +- **[Production Deployment](/runagent-cloud/cloud-deployment)** - Deploy to production - **[Multi-Language Access](/tutorials/multi-language-wrapper)** - Access from different languages - **[Performance Tuning](/explanation/production-considerations)** - Optimize for production diff --git a/docs/how-to/frameworks/parlant.mdx b/docs/how-to/frameworks/parlant.mdx index 1e41622..06c3f7f 100644 --- a/docs/how-to/frameworks/parlant.mdx +++ b/docs/how-to/frameworks/parlant.mdx @@ -1047,7 +1047,7 @@ class SessionPool: ## Next Steps - **[Advanced Patterns](/how-to/advanced-tasks)** - Learn advanced Parlant patterns -- **[Production Deployment](/how-to/deployment/cloud-deployment)** - Deploy to production +- **[Production Deployment](/runagent-cloud/cloud-deployment)** - Deploy to production - **[Multi-Language Access](/tutorials/multi-language-wrapper)** - Access from different languages - **[Performance Tuning](/explanation/production-considerations)** - Optimize for production diff --git a/docs/how-to/overview.mdx b/docs/how-to/overview.mdx index 151ee1f..86a44bb 100644 --- a/docs/how-to/overview.mdx +++ b/docs/how-to/overview.mdx @@ -33,8 +33,8 @@ Pick a task and follow the steps. Each guide is 5–10 minutes. ## Operations - - + + diff --git a/docs/runagent-cloud/cloud-deployment.mdx b/docs/runagent-cloud/cloud-deployment.mdx new file mode 100644 index 0000000..bd79a85 --- /dev/null +++ b/docs/runagent-cloud/cloud-deployment.mdx @@ -0,0 +1,625 @@ +--- +title: 'Cloud Deployment' +description: 'Deploy agents to RunAgent cloud infrastructure' +--- + +Deploy agents to RunAgent cloud infrastructure for production use with automatic scaling, monitoring, and global availability. + +## Prerequisites + +Before deploying to the cloud, you need: + +1. **RunAgent Account** - Sign up at [run-agent.ai](https://run-agent.ai) +2. **API Key** - Get your API key from the dashboard +3. **Configured CLI** - Authenticate your CLI with your API key + +## Authentication Setup + +Configure your CLI with your API key: + +```bash +# Setup authentication +runagent setup --api-key + +# Verify configuration +runagent setup --api-key +``` + +The setup command will: +- Validate your API key with the RunAgent middleware +- Store credentials securely in `~/.runagent/config.json` +- Display your account information and tier +- Show middleware sync status + +### Teardown Configuration + +Remove stored credentials: + +```bash +runagent teardown +``` + +## Deployment Methods + +### Method 1: Quick Deploy (Upload + Start) + +Deploy your agent in a single command: + +```bash +# Deploy to cloud (combines upload + start) +runagent deploy --folder + +# Example +runagent deploy --folder ./my-agent +``` + +This command will: +1. Validate your agent configuration +2. Upload agent code and metadata to the cloud +3. Start the agent automatically +4. Return the deployment endpoint + +**Output:** +``` +βœ… Full deployment successful! +πŸ†” Agent ID: abc-123-def-456 +🌐 Endpoint: https://api.run-agent.ai/api/v1/agents/abc-123-def-456 +``` + +### Method 2: Two-Step Deploy (Upload Then Start) + +For more control, upload and start separately: + +#### Step 1: Upload Agent + +```bash +# Upload agent to cloud +runagent upload --folder + +# Specify framework explicitly (optional) +runagent upload --folder --framework langgraph +``` + +**Upload Process:** +1. Agent validation (checks for required files) +2. Fingerprint generation (for duplicate detection) +3. Metadata upload (config + entrypoints) +4. Source code packaging and upload +5. Local database tracking + +**Output:** +``` +πŸ“€ Uploading agent from: ./my-agent +πŸ” Validating agent... +βœ… Agent validation passed +πŸ“‹ Agent config loaded successfully +πŸ” Agent fingerprint: a1b2c3d4... + +πŸ“¦ Uploading to: https://api.run-agent.ai/api/v1 +🌐 Uploading agent metadata... + Metadata uploaded successfully +πŸ“¦ Creating upload package... + Created upload package: agent_abc12345.zip + Uploading agent_abc12345.zip (1,234,567 bytes)... + Processing upload... + Upload completed! + +βœ… Upload successful! +πŸ†” Agent ID: abc-123-def-456 +🌐 Server: https://api.run-agent.ai/api/v1 +πŸ” Fingerprint: a1b2c3d4... + +πŸ’‘ Next step: runagent start --id abc-123-def-456 +``` + +#### Step 2: Start Agent + +```bash +# Start uploaded agent +runagent start --id + +# With custom configuration +runagent start --id --config '{"env": "production"}' +``` + +**Output:** +``` +Starting agent: abc-123-def-456 + +βœ… Agent started successfully! +πŸ†” Agent ID: abc-123-def-456 +🌐 Endpoint: https://api.run-agent.ai/api/v1/agents/abc-123-def-456/execute +``` + +## Agent Configuration + +### Agent ID and Entrypoints + +When you initialize a new agent with `runagent init`, it automatically: +1. **Generates a unique agent ID** and adds it to `runagent.config.json` +2. **Creates a basic configuration** with framework and template settings + +**Important:** You must add your entrypoints to the configuration file before deploying. + +#### Using `runagent init` (Recommended) + +```bash +# Initialize a new agent +runagent init my-agent --framework langgraph + +# This creates runagent.config.json with: +# - Generated agent_id +# - Framework configuration +# - Empty entrypoints array (you need to add these) +``` + +**Example `runagent.config.json` after init:** +```json +{ + "agent_name": "my-agent", + "agent_id": "abc-123-def-456", + "version": "1.0.0", + "framework": "langgraph", + "agent_architecture": { + "entrypoints": [] // ← You need to add entrypoints here + } +} +``` + +**Add your entrypoints:** +```json +{ + "agent_name": "my-agent", + "agent_id": "abc-123-def-456", + "version": "1.0.0", + "framework": "langgraph", + "agent_architecture": { + "entrypoints": [ + { + "tag": "chat", + "file": "main.py", + "module": "chat_agent" + }, + { + "tag": "chat_stream", + "file": "main.py", + "module": "chat_agent_stream" + } + ] + } +} +``` + +#### Manually Editing Agent ID + +If you manually edit the `agent_id` in `runagent.config.json`, you **must register** the agent: + +```bash +# Register the agent after manually editing agent_id +runagent register . + +# Or use the config command +runagent config --register-agent . +``` + + +**Important:** If you manually change the `agent_id` in your config file, RunAgent won't recognize it until you register it. Always run `runagent register .` after manually editing the agent ID. + + +## Agent Validation + +Before upload, RunAgent validates your agent: + +### Required Files +- `runagent.config.json` - Agent configuration with valid `agent_id` and `entrypoints` +- `main.py` or `agent.py` - Entry point file +- `requirements.txt` - Python dependencies (optional) + +### Validation Checks +- βœ… Configuration file exists and is valid JSON +- βœ… Agent ID exists in configuration +- βœ… Agent ID is registered (if manually edited) +- βœ… Entry point file exists +- βœ… Entrypoints are properly defined +- βœ… Framework is supported +- βœ… No syntax errors in configuration + +**Example Valid Configuration:** +```json +{ + "agent_name": "my-agent", + "agent_id": "abc-123-def-456", + "version": "1.0.0", + "framework": "langgraph", + "agent_architecture": { + "entrypoints": [ + { + "tag": "chat", + "file": "main.py", + "module": "agent.chat" + } + ] + } +} +``` + +## Duplicate Detection + +RunAgent uses fingerprinting to detect duplicate agents: + +### How It Works +1. **Fingerprint Generation**: Creates a unique hash of your agent's content +2. **Duplicate Check**: Compares with existing agents in your account +3. **User Prompt**: If duplicate found, asks whether to overwrite or create new + +**Example Scenarios:** + +**Scenario 1: Identical Content** +``` +⚠️ Agent with identical content already exists! +πŸ†” Existing Agent ID: abc-123-def-456 +πŸ“Š Status: deployed +πŸ“ Type: Remote + +Do you want to overwrite the existing agent? [y/N]: +``` + +**Scenario 2: Modified Content** +``` +⚠️ Agent content has changed! +πŸ†” Existing Agent ID: abc-123-def-456 +πŸ“Š Status: deployed +πŸ“ Type: Remote +πŸ” Content fingerprint changed (modified files detected) + +What would you like to do? + [overwrite] - Overwrite existing agent (coming soon) + [new] - Create new agent + [cancel] - Cancel upload +``` + +## Running Cloud Agents + +Execute your deployed agents: + +### Basic Execution + +```bash +# Run with entrypoint tag +runagent run --id --tag --param1=value1 --param2=value2 + +# Examples +runagent run --id abc-123 --tag chat --message="Hello" +runagent run --id abc-123 --tag process --data='{"key": "value"}' +``` + +### Using Input Files + +```bash +# Run with JSON input file +runagent run --id --tag --input config.json +``` + +**Example input.json:** +```json +{ + "message": "Hello, world!", + "config": { + "temperature": 0.7, + "max_tokens": 100 + } +} +``` + +### Streaming Execution + +For streaming entrypoints (must end with `_stream`): + +```bash +# Run streaming endpoint using run-stream command +runagent run-stream --id --tag chat_stream --message="Tell me a story" + +# Or with local agent +runagent run-stream --id --tag chat_stream --local --message="Tell me a story" +``` + + +**Important:** Use `runagent run-stream` (not `runagent run`) for streaming execution. The `run-stream` command uses WebSocket connections for real-time streaming. + + +## Cloud vs Local Deployment + +| Feature | Local | Cloud | +|---------|-------|-------| +| **Setup** | `runagent serve` | `runagent deploy` | +| **Infrastructure** | Your machine | RunAgent cloud | +| **Scaling** | Manual | Automatic | +| **Uptime** | While running | 24/7 | +| **Monitoring** | Local logs only | Full monitoring dashboard | +| **URL** | localhost:port | Global endpoint | +| **Authentication** | None | API key required | +| **Cost** | Free | Usage-based pricing | + +## Deployment Workflow + +### Complete Example + +```bash +# 1. Create and test agent locally +runagent init my-agent --framework langgraph --template default +cd my-agent + +# 2. Add entrypoints to runagent.config.json +# Edit the file and add your entrypoints to agent_architecture.entrypoints + +# 3. If you manually edited agent_id, register it +runagent register . + +# 4. Test locally +runagent serve + +# 5. Authenticate (if not already done) +runagent setup --api-key + +# 6. Deploy to cloud +runagent deploy --folder . + +# 7. Test cloud deployment +runagent run --id --tag chat --message="Hello" +``` + +### CI/CD Integration + +#### GitHub Actions + +```yaml +name: Deploy to RunAgent Cloud + +on: + push: + branches: [main] + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: '3.9' + + - name: Install RunAgent + run: pip install runagent + + - name: Deploy Agent + env: + RUNAGENT_API_KEY: ${{ secrets.RUNAGENT_API_KEY }} + run: | + runagent setup --api-key $RUNAGENT_API_KEY + runagent deploy --folder . +``` + +#### GitLab CI + +```yaml +deploy: + stage: deploy + image: python:3.9 + + script: + - pip install runagent + - runagent setup --api-key $RUNAGENT_API_KEY + - runagent deploy --folder . + + only: + - main +``` + +## Monitoring and Management + +### View Agent Status + +```bash +# Check if agent is running +runagent start --id +``` + +### Local Deployment Info + +Deployment information is saved locally in `.deployments/`: + +```json +{ + "agent_id": "abc-123-def-456", + "remote": true, + "base_url": "https://api.run-agent.ai/api/v1", + "fingerprint": "a1b2c3d4...", + "source_folder": "/path/to/my-agent", + "saved_at": "2025-01-15 10:30:00", + "client_version": "1.0" +} +``` + +## Troubleshooting + +### Authentication Errors + +**Error:** `Not authenticated. Run 'runagent setup --api-key ' first` + +**Solution:** +```bash +# Setup authentication +runagent setup --api-key + +# Verify setup worked +runagent setup --api-key +``` + +### Upload Failures + +**Error:** `Agent validation failed` + +**Solution:** +1. Check that `runagent.config.json` exists and is valid +2. Verify entry point file exists (`main.py` or `agent.py`) +3. Ensure all required dependencies are in `requirements.txt` +4. Run `runagent serve` locally to test first + +**Error:** `Failed to upload agent: HTTP 413` + +**Solution:** Your agent folder is too large. Remove unnecessary files: +- Remove `__pycache__` directories +- Remove `.pyc` files +- Remove large data files (use cloud storage instead) +- Add `.gitignore` patterns to exclude files + +### Deployment Fails But Upload Succeeds + +**Error:** `Upload succeeded but start failed` + +**Solution:** +```bash +# Agent is uploaded, just needs to be started +runagent start --id +``` + +### Connection Issues + +**Error:** `Cannot connect to middleware server` + +**Solution:** +1. Check your internet connection +2. Verify the base URL is correct +3. Check if middleware server is accessible +4. Try with explicit base URL: `runagent setup --api-key --base-url https://api.run-agent.ai` + +## Best Practices + +### 1. Test Locally First + +Always test your agent locally before deploying: + +```bash +# Test locally +runagent serve +runagent run --id --tag chat --local --message="test" + +# Deploy after successful local testing +runagent deploy --folder . +``` + +### 2. Version Control + +Include deployment info in version control: + +```bash +# Add to .gitignore +.deployments/*.json +.runagent/ + +# But track your agent code +git add runagent.config.json main.py requirements.txt +git commit -m "feat: add chat agent" +``` + +### 3. Environment Variables + +Use environment variables for sensitive data: + +```json +{ + "env_vars": { + "OPENAI_API_KEY": "${OPENAI_API_KEY}", + "DATABASE_URL": "${DATABASE_URL}" + } +} +``` + +Set them before deploying: +```bash +export OPENAI_API_KEY="sk-..." +runagent deploy --folder . +``` + +### 4. Incremental Updates + +For agent updates: + +```bash +# Upload new version +runagent upload --folder . + +# Test before switching +runagent run --id --tag chat --message="test" + +# If good, can use new agent ID +``` + +### 5. Monitor Performance + +After deployment: +- Test all entrypoints +- Check response times +- Verify outputs are correct +- Monitor error rates + +## Security + +### API Key Management + +**Best Practices:** +- βœ… Store API keys in environment variables +- βœ… Use different keys for development and production +- βœ… Rotate keys regularly +- βœ… Never commit API keys to version control +- ❌ Don't share API keys +- ❌ Don't hardcode keys in agent code + +### Secure Deployment + +```bash +# Use environment variables +export RUNAGENT_API_KEY="your-key" +runagent deploy --folder . + +# Or use secure config file +runagent setup --api-key $RUNAGENT_API_KEY +``` + +## Limits and Quotas + +### Free Tier +- 5 local agents +- Cloud deployment available +- Standard execution limits + +### Enhanced Limits +Contact sales for: +- Unlimited local agents +- Higher execution limits +- Priority support +- Custom SLAs + +Check your current limits: +```bash +runagent db status --capacity +``` + +## Next Steps + +- [RunAgent Cloud Overview](/runagent-cloud/overview) - Learn about RunAgent Cloud infrastructure +- [Local Development](/deployment/local-development) - Test agents locally +- [SDK Overview](/sdk/overview) - Use Python SDK for deployment +- [API Reference](/api-reference) - Direct API access +- [Monitoring Guide](/explanation/production-considerations) - Track agent performance + +## Support + +Need help with cloud deployment? +- πŸ“– [Documentation](https://docs.run-agent.ai) +- πŸ’¬ [Discord Community](https://discord.gg/runagent) +- πŸ“§ [Email Support](mailto:support@run-agent.ai) +- πŸ› [Report Issues](https://github.com/runagent/runagent/issues) \ No newline at end of file diff --git a/docs/runagent-cloud/overview.mdx b/docs/runagent-cloud/overview.mdx new file mode 100644 index 0000000..9939c6d --- /dev/null +++ b/docs/runagent-cloud/overview.mdx @@ -0,0 +1,166 @@ +--- +title: 'RunAgent Cloud Overview' +description: 'Serverless infrastructure for deploying and running AI agents at scale' +icon: 'cloud' +--- + +import NeedHelp from '/snippets/need-help.mdx'; + +> RunAgent Cloud provides a fully managed, serverless infrastructure for deploying and running your AI agents. No infrastructure management, automatic scaling, and global availability. + +## What is RunAgent Cloud? + +RunAgent Cloud is a serverless platform designed specifically for AI agents. It handles all the infrastructure complexity so you can focus on building great agents. + +### Key Benefits + + + + Fully managed infrastructure with zero configuration. Deploy and scale automatically. + + + Scale from zero to thousands of requests without manual intervention. + + + Deploy once, access from anywhere with low-latency global distribution. + + + Automatic image selection based on your agent's requirements and dependencies. + + + +## Serverless Infrastructure + +RunAgent Cloud operates on a serverless model where: + +- **No servers to manage** - Infrastructure is fully managed by RunAgent +- **Pay per use** - Only pay for actual agent execution time +- **Automatic scaling** - Handles traffic spikes without configuration +- **Zero maintenance** - Updates, patches, and security handled automatically +- **High availability** - Built-in redundancy and failover + +### How It Works + +1. **Deploy your agent** - Upload your agent code with a single command +2. **Automatic provisioning** - RunAgent Cloud selects the optimal VM image +3. **On-demand execution** - Agents start when needed, scale automatically +4. **Global distribution** - Requests routed to nearest available instance + +## VM Image Management + +RunAgent Cloud supports multiple VM images optimized for different use cases and dependencies. + +### Automatic Image Selection + +The platform automatically selects the appropriate VM image based on: + +- **Framework requirements** - LangGraph, CrewAI, custom frameworks +- **Dependencies** - Python packages, system libraries +- **Resource needs** - CPU, memory, GPU requirements +- **Optimization** - Best performance for your specific agent + +You don't need to specify which image to use - RunAgent Cloud handles this automatically. + +### Deployment Time + +Initial deployment time varies based on the selected VM image: + +- **Standard images**: Typically ready in 30-60 seconds +- **Specialized images**: May take up to 2 minutes for first deployment +- **Subsequent requests**: Cached images start in seconds + +The platform optimizes for your agent's specific needs, which may require pulling specialized images on first deployment. + +### Image Availability + +RunAgent Cloud currently supports multiple VM images optimized for: + +- Python-based agents with various framework requirements +- Different dependency sets and system library needs +- Performance-optimized configurations + +**More VM images coming soon** - We're continuously expanding image support to cover additional frameworks, languages, and use cases. + +## Getting Started + +### Quick Start + +```bash +# 1. Authenticate with RunAgent Cloud +runagent setup --api-key + +# 2. Deploy your agent +runagent deploy --folder ./my-agent + +# 3. Your agent is live and accessible globally +``` + +### Next Steps + + + + Complete guide to deploying agents to RunAgent Cloud + + + Test agents locally before deploying to cloud + + + Set up API keys and authentication + + + Monitor and manage your deployed agents + + + +## Architecture + +RunAgent Cloud provides: + +- **Isolated execution environments** - Each agent runs in its own secure container +- **Load balancing** - Automatic request distribution across instances +- **Health monitoring** - Continuous health checks and automatic recovery +- **Logging and metrics** - Comprehensive observability for all agents +- **API gateway** - Unified interface for all agent interactions + +## Pricing Model + +RunAgent Cloud uses a usage-based pricing model: + +- **No upfront costs** - Pay only for what you use +- **Per-execution pricing** - Based on actual agent runtime +- **Transparent billing** - Clear visibility into usage and costs +- **Free tier available** - Get started with free credits + +## Security + +RunAgent Cloud includes enterprise-grade security: + +- **Isolated execution** - Complete isolation between agents +- **Encrypted connections** - All traffic encrypted in transit +- **API key authentication** - Secure access control +- **Audit logging** - Complete activity tracking +- **Compliance ready** - Built with security best practices + +## Comparison: Local vs Cloud + +| Feature | Local Development | RunAgent Cloud | +|---------|------------------|----------------| +| **Setup** | Manual configuration | Zero configuration | +| **Scaling** | Manual | Automatic | +| **Availability** | When your machine is on | 24/7 global | +| **Maintenance** | You manage | Fully managed | +| **Cost** | Free (your infrastructure) | Pay per use | +| **Best for** | Development, testing | Production | + +## Support and Resources + +- **Documentation** - Comprehensive guides and references +- **Dashboard** - Web interface for managing agents +- **Community** - Discord community for support +- **Status page** - Real-time platform status + +## Next Steps + +Ready to deploy to RunAgent Cloud? Start with the [Cloud Deployment Guide](/runagent-cloud/cloud-deployment) to learn how to deploy your first agent. + + diff --git a/docs/tutorials/book-writer.mdx b/docs/tutorials/book-writer.mdx new file mode 100644 index 0000000..62d70c7 --- /dev/null +++ b/docs/tutorials/book-writer.mdx @@ -0,0 +1,383 @@ +--- +title: 'Book Writing Agent' +description: 'Build an AI agent that writes complete books using multi-agent workflows' +icon: 'book' +--- + +import NeedHelp from '/snippets/need-help.mdx'; + + + **Prerequisites**: Completed the [Deploy Your First Agent](/tutorials/deploy-your-first-agent) tutorial + + +## What You'll Build + +In this tutorial, you'll create a book writing agent that: +- Generates comprehensive book outlines based on topics and goals +- Writes complete books chapter by chapter using specialized agents +- Orchestrates multiple AI agents to handle different writing tasks +- Produces well-structured, coherent book content +- Uses CrewAI flows for multi-agent collaboration + +## The Book Writing Challenge + +Writing a complete book is a complex, multi-stage process: +- **Outline creation**: Structuring the book logically +- **Chapter writing**: Writing detailed, coherent chapters +- **Consistency**: Maintaining tone and style across chapters +- **Research**: Gathering relevant information +- **Time investment**: Writing a book takes months or years + +RunAgent solves this by orchestrating multiple specialized AI agents that work together to create complete books efficiently. + +## Architecture Overview + +The book writing agent uses a multi-agent workflow: + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ User Input β”‚ +β”‚ (Topic, Goal) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ OutlineCrew β”‚ +β”‚ (Generate β”‚ +β”‚ Book Outline) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ WriteBook β”‚ +β”‚ ChapterCrew β”‚ +β”‚ (One per β”‚ +β”‚ chapter) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Join Chapters β”‚ +β”‚ & Save Book β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +## Step 1: Understanding the Agent Structure + +The book writing agent uses CrewAI flows with specialized crews: + +**Key Components:** +- **OutlineCrew**: Generates comprehensive book outlines + - Searches the internet for relevant information + - Defines book structure and main topics + - Creates detailed chapter breakdowns + +- **WriteBookChapterCrew**: Writes individual chapters + - One crew instance per chapter + - Ensures detailed and coherent content + - Maintains consistency with outline + +**Entrypoints:** +- `generate_outline`: Generate book outline from topic and goal +- `write_book`: Write complete book with all chapters + +## Step 2: Agent Configuration + +The agent is configured using `runagent.config.json`: + +```json +{ + "agent_name": "book-writer", + "description": "AI-powered book writing with multi-agent workflows", + "framework": "crewai", + "agent_architecture": { + "entrypoints": [ + { + "file": "main.py", + "module": "generate_outline", + "tag": "generate_outline" + }, + { + "file": "main.py", + "module": "write_book", + "tag": "write_book" + } + ] + } +} +``` + +## Step 3: Core Agent Logic (Gist) + +The agent writes books through a structured workflow: + +```python +# Simplified flow structure +def generate_outline( + title: str, + topic: str, + goal: str +) -> Dict[str, Any]: + """ + Generates a comprehensive book outline: + 1. Researches the topic using web search + 2. Defines book structure and main topics + 3. Creates detailed chapter breakdowns + 4. Returns structured outline + """ + outline_crew = OutlineCrew() + result = outline_crew.kickoff( + title=title, + topic=topic, + goal=goal + ) + return result + +def write_book( + title: str, + topic: str, + goal: str, + num_chapters: int = 5 +) -> Dict[str, Any]: + """ + Writes a complete book: + 1. Generates book outline + 2. Creates WriteBookChapterCrew for each chapter + 3. Writes each chapter in parallel or sequentially + 4. Joins all chapters into a single markdown file + 5. Saves the complete book + """ + # Generate outline + outline = generate_outline(title, topic, goal) + + # Write each chapter + chapters = [] + for chapter_info in outline['chapters']: + chapter_crew = WriteBookChapterCrew() + chapter = chapter_crew.kickoff( + title=title, + chapter_info=chapter_info, + previous_chapters=chapters + ) + chapters.append(chapter) + + # Join and save + complete_book = join_chapters(title, chapters) + save_book(complete_book) + + return { + "title": title, + "chapters": chapters, + "complete_book": complete_book + } +``` + +## Step 4: Backend Integration + +The Flask backend provides REST API endpoints: + +```python +# Backend API structure +@app.route('/api/generate-outline', methods=['POST']) +def generate_outline(): + """ + Endpoint that: + - Receives book topic and goal + - Calls RunAgent agent to generate outline + - Returns structured outline + """ + client = RunAgentClient( + agent_id=agent_id, + entrypoint_tag="generate_outline", + local=False + ) + + result = client.run( + title=title, + topic=topic, + goal=goal + ) + + return jsonify(result) + +@app.route('/api/write-book', methods=['POST']) +def write_book(): + """ + Endpoint that: + - Receives book parameters + - Calls RunAgent agent to write complete book + - Returns book content or file + """ + client = RunAgentClient( + agent_id=agent_id, + entrypoint_tag="write_book", + local=False + ) + + result = client.run( + title=title, + topic=topic, + goal=goal, + num_chapters=num_chapters + ) + + return jsonify(result) +``` + +## Step 5: Frontend Integration + +The React frontend provides a user-friendly interface: + +**Key Features:** +- Book title and topic input +- Goal description input +- Outline preview +- Chapter-by-chapter writing progress +- Complete book download +- Real-time status updates + +## Step 6: Deployment + +### Local Deployment + +```bash +# 1. Deploy the RunAgent agent +cd examples/book_writer/write_a_book_with_flows +runagent serve . + +# 2. Start the backend +cd ../backend +python app.py + +# 3. Start the frontend +cd ../frontend +npm run dev +``` + +### Production Deployment + +The agent can be deployed to RunAgent Cloud: + +```bash +runagent deploy . +``` + +## What You've Accomplished + +You've built a complete book writing system: + + + + Automated book writing from topic to complete manuscript + + + Orchestrated multiple specialized agents for different tasks + + + Generates well-structured outlines and coherent chapters + + + Automatically researches topics using web search + + + +## Key Features + +### Outline Generation +- Researches topics using web search +- Creates logical book structure +- Defines main topics and chapter breakdowns +- Ensures comprehensive coverage + +### Chapter Writing +- Writes detailed, coherent chapters +- Maintains consistency across chapters +- References previous chapters for continuity +- Adapts to book outline structure + +### Multi-Agent Orchestration +- Uses CrewAI flows to coordinate agents +- Parallel or sequential chapter writing +- Specialized agents for different tasks +- Efficient resource utilization + +## Example Usage + +```python +from runagent import RunAgentClient + +# Generate outline +outline_client = RunAgentClient( + agent_id="your_agent_id", + entrypoint_tag="generate_outline", + local=False +) + +outline = outline_client.run( + title="Introduction to AI", + topic="Artificial Intelligence", + goal="Provide a comprehensive introduction to AI for beginners" +) + +# Write complete book +book_client = RunAgentClient( + agent_id="your_agent_id", + entrypoint_tag="write_book", + local=False +) + +book = book_client.run( + title="Introduction to AI", + topic="Artificial Intelligence", + goal="Provide a comprehensive introduction to AI for beginners", + num_chapters=5 +) +``` + +## Customization + +### Adjusting Book Structure +- Modify `config/agents.yaml` to customize agent behavior +- Update `config/tasks.yaml` to change writing tasks +- Adjust flow in `main.py` for different workflows + +### Adding Features +- Add research agents for deeper topic exploration +- Include editing agents for content refinement +- Add formatting agents for different output formats + +## Next Steps + + + + Customize agent prompts and behaviors + + + Add features like editing, formatting, and publishing + + + Deploy to production with proper scaling + + + Explore the complete example code + + + +## Repository + +View the complete example code and documentation: + +**Repository**: [https://github.com/runagent-dev/runagent/tree/main/examples/book_writer](https://github.com/runagent-dev/runagent/tree/main/examples/book_writer) + +The repository includes: +- Complete agent implementation with CrewAI flows +- Flask backend API +- React frontend application +- Configuration files for agents and tasks +- Example outputs and documentation + + +**πŸŽ‰ Excellent work!** You've learned how to build a sophisticated book writing system using RunAgent and CrewAI. This demonstrates the power of multi-agent orchestration for complex creative tasks! + + + diff --git a/docs/tutorials/customer-support-agent.mdx b/docs/tutorials/customer-support-agent.mdx deleted file mode 100644 index b4128c3..0000000 --- a/docs/tutorials/customer-support-agent.mdx +++ /dev/null @@ -1,469 +0,0 @@ ---- -title: 'Customer Support Agent' -description: 'Build a customer support chatbot with streaming responses' -icon: 'headset' ---- - -import NeedHelp from '/snippets/need-help.mdx'; - - - **Prerequisites**: Completed the [Deploy Your First Agent](/tutorials/deploy-your-first-agent) tutorial - - -## What You'll Build - -In this tutorial, you'll create a customer support agent that: -- Answers common questions about your product -- Provides streaming responses for better user experience -- Can be integrated into any web application -- Handles multiple conversation flows - -## The Customer Support Challenge - -Every business needs customer support, but building a good chatbot is hard: -- **Knowledge management**: Keeping FAQs up-to-date -- **Response quality**: Making answers helpful and accurate -- **Integration**: Embedding in websites and apps -- **Scalability**: Handling multiple users simultaneously - -RunAgent solves all of these by letting you focus on the AI logic while handling the infrastructure. - -## Step 1: Create Your Support Agent - -Let's start by creating a new agent specifically for customer support: - -```bash -runagent init customer-support --framework custom -cd customer-support -``` - -This creates a clean slate for your support agent. - -## Step 2: Build the Support Logic - -Replace the contents of `main.py` with a customer support agent: - -```python main.py -from typing import Iterator, Dict, Any -import json - -class CustomerSupportAgent: - def __init__(self): - # Knowledge base - in production, this would be a database - self.knowledge_base = { - "pricing": { - "basic": "$9/month - Up to 1000 requests", - "pro": "$29/month - Up to 10,000 requests", - "enterprise": "Custom pricing - Unlimited requests" - }, - "features": [ - "Multi-language SDKs (Python, JavaScript, Rust, Go)", - "Real-time streaming responses", - "Auto-scaling infrastructure", - "Framework integrations (LangGraph, CrewAI, etc.)" - ], - "troubleshooting": { - "connection": "Check your API key and agent ID", - "timeout": "Increase timeout settings or check network", - "streaming": "Ensure your entrypoint tag ends with '_stream'" - } - } - - def categorize_query(self, message: str) -> str: - """Categorize the customer query""" - message_lower = message.lower() - - if any(word in message_lower for word in ["price", "cost", "pricing", "plan"]): - return "pricing" - elif any(word in message_lower for word in ["feature", "capability", "what can"]): - return "features" - elif any(word in message_lower for word in ["help", "problem", "error", "issue", "troubleshoot"]): - return "troubleshooting" - else: - return "general" - -def customer_support_sync(message: str, user_id: str = "anonymous") -> Dict[str, Any]: - """Synchronous customer support response""" - agent = CustomerSupportAgent() - category = agent.categorize_query(message) - - response = { - "message": "", - "category": category, - "user_id": user_id, - "timestamp": "2024-01-01T00:00:00Z" # In production, use actual timestamp - } - - if category == "pricing": - response["message"] = f"""Here are our current pricing plans: - -**Basic Plan**: {agent.knowledge_base['pricing']['basic']} -- Perfect for small projects and testing - -**Pro Plan**: {agent.knowledge_base['pricing']['pro']} -- Great for growing applications - -**Enterprise Plan**: {agent.knowledge_base['pricing']['enterprise']} -- Custom solutions for large organizations - -Would you like to know more about any specific plan?""" - - elif category == "features": - features_list = "\n".join([f"β€’ {feature}" for feature in agent.knowledge_base['features']]) - response["message"] = f"""RunAgent offers these key features: - -{features_list} - -Is there a specific feature you'd like to learn more about?""" - - elif category == "troubleshooting": - response["message"] = """I'd be happy to help troubleshoot! Here are some common solutions: - -β€’ **Connection issues**: Check your API key and agent ID -β€’ **Timeout errors**: Increase timeout settings or check your network -β€’ **Streaming problems**: Ensure your entrypoint tag ends with '_stream' - -Can you describe the specific issue you're experiencing?""" - - else: - response["message"] = """Hello! I'm here to help with any questions about RunAgent. - -I can help you with: -β€’ Pricing and plans -β€’ Features and capabilities -β€’ Technical troubleshooting -β€’ Getting started guides - -What would you like to know?""" - - return response - -def customer_support_stream(message: str, user_id: str = "anonymous") -> Iterator[str]: - """Streaming customer support response""" - agent = CustomerSupportAgent() - category = agent.categorize_query(message) - - # Stream the response with typing effect - if category == "pricing": - yield "Let me check our current pricing for you...\n\n" - yield "**Basic Plan**: $9/month - Up to 1000 requests\n" - yield "Perfect for small projects and testing\n\n" - yield "**Pro Plan**: $29/month - Up to 10,000 requests\n" - yield "Great for growing applications\n\n" - yield "**Enterprise Plan**: Custom pricing - Unlimited requests\n" - yield "Custom solutions for large organizations\n\n" - yield "Would you like to know more about any specific plan?" - - elif category == "features": - yield "Here are RunAgent's key features:\n\n" - for feature in agent.knowledge_base['features']: - yield f"β€’ {feature}\n" - yield "\nIs there a specific feature you'd like to learn more about?" - - elif category == "troubleshooting": - yield "I'd be happy to help troubleshoot!\n\n" - yield "Here are some common solutions:\n\n" - yield "β€’ **Connection issues**: Check your API key and agent ID\n" - yield "β€’ **Timeout errors**: Increase timeout settings or check your network\n" - yield "β€’ **Streaming problems**: Ensure your entrypoint tag ends with '_stream'\n\n" - yield "Can you describe the specific issue you're experiencing?" - - else: - yield "Hello! I'm here to help with any questions about RunAgent.\n\n" - yield "I can help you with:\n" - yield "β€’ Pricing and plans\n" - yield "β€’ Features and capabilities\n" - yield "β€’ Technical troubleshooting\n" - yield "β€’ Getting started guides\n\n" - yield "What would you like to know?" -``` - -## Step 3: Configure Your Agent - -Update `runagent.config.json` to include both sync and streaming entrypoints: - -```json -{ - "agent_name": "customer-support", - "description": "AI-powered customer support agent", - "framework": "custom", - "agent_architecture": { - "entrypoints": [ - { - "file": "main.py", - "module": "customer_support_sync", - "tag": "support" - }, - { - "file": "main.py", - "module": "customer_support_stream", - "tag": "support_stream" - } - ] - } -} -``` - -## Step 4: Deploy Your Support Agent - -Start your customer support agent: - -```bash -runagent serve . -``` - -You should see output like: -``` -πŸ€– Agent Details: -- Agent ID: support_agent_123 -- Host: 127.0.0.1 -- Port: 8451 -- Framework: custom -- Status: ready - -🌐 Server running at: http://127.0.0.1:8451 -πŸ“– API Documentation: http://127.0.0.1:8451/docs - -πŸ“ Available endpoints: -- POST /api/v1/agents/.../execute/support - Run your agent -- POST /api/v1/agents/.../execute/support_stream - Stream your agent -``` - -## Step 5: Test Your Support Agent - -### Test Synchronous Responses - -```python -from runagent import RunAgentClient - -# Connect to your support agent -support = RunAgentClient( - agent_id="support_agent_123", - entrypoint_tag="support", - local=True -) - -# Test different types of queries -queries = [ - "What are your pricing plans?", - "What features does RunAgent offer?", - "I'm having connection issues", - "Hello, I need help" -] - -for query in queries: - print(f"\nQuery: {query}") - response = support.run(message=query, user_id="test_user") - print(f"Response: {response['message']}") - print(f"Category: {response['category']}") -``` - -### Test Streaming Responses - -```python -# Test streaming for better user experience -support_stream = RunAgentClient( - agent_id="support_agent_123", - entrypoint_tag="support_stream", - local=True -) - -print("Streaming response:") -for chunk in support_stream.run(message="What are your pricing plans?", user_id="test_user"): - print(chunk, end="", flush=True) -``` - -## Step 6: Build a Simple Web Interface - -Create a simple HTML file to demonstrate the support agent in action: - -```html support_demo.html - - - - RunAgent Customer Support - - - -

RunAgent Customer Support

-
-
- - -
- - - - -``` - -## Step 7: Test the Web Interface - -1. Open `support_demo.html` in your browser -2. Try asking questions like: - - "What are your pricing plans?" - - "What features do you offer?" - - "I'm having connection issues" - - "How do I get started?" - -## What You've Accomplished - -In this tutorial, you've built a complete customer support system: - - - - Created an intelligent agent that categorizes and responds to customer queries - - - Implemented streaming responses for better user experience - - - Built a web interface that can be embedded anywhere - - - Added intelligent query classification for better responses - - - -## Next Steps - -### Enhance Your Support Agent - -1. **Add more knowledge**: Expand the knowledge base with more FAQs -2. **Database integration**: Connect to a real database for dynamic content -3. **User authentication**: Track user sessions and history -4. **Analytics**: Add logging and metrics collection -5. **Multi-language support**: Add support for different languages - -### Production Deployment - -1. **Environment variables**: Move configuration to environment variables -2. **Error handling**: Add robust error handling and fallbacks -3. **Rate limiting**: Implement rate limiting for API calls -4. **Monitoring**: Add health checks and monitoring -5. **Scaling**: Deploy to cloud with auto-scaling - -## Common Support Patterns - - - - Keep your knowledge base updated and organized. Consider using a vector database for semantic search. - - - Add logic to escalate complex queries to human agents when needed. - - - Implement conversation memory to maintain context across multiple exchanges. - - - Use webhooks to integrate with your existing support systems and CRM. - - - -## Ready for More? - - - - Learn how to call your support agent from different programming languages - - - Integrate with advanced AI frameworks for more sophisticated responses - - - Deploy your support agent to production with proper scaling - - - Add advanced features like memory, context, and analytics - - - - -**πŸŽ‰ Great job!** You've built a production-ready customer support agent that can be integrated into any application. This is just the beginning of what you can create with RunAgent! - - - diff --git a/docs/tutorials/deploy-your-first-agent.mdx b/docs/tutorials/deploy-your-first-agent.mdx index bbb26df..8c1b781 100644 --- a/docs/tutorials/deploy-your-first-agent.mdx +++ b/docs/tutorials/deploy-your-first-agent.mdx @@ -533,7 +533,7 @@ In these 5 minutes, you've experienced something revolutionary: See production-ready agents built with popular frameworks - + Scale your agents to serve millions of requests diff --git a/docs/tutorials/internal-qa-agent.mdx b/docs/tutorials/internal-qa-agent.mdx deleted file mode 100644 index a89fc1a..0000000 --- a/docs/tutorials/internal-qa-agent.mdx +++ /dev/null @@ -1,816 +0,0 @@ ---- -title: 'Internal Q&A Agent' -description: 'Build an internal knowledge base agent for your team' -icon: 'question-circle' ---- - -import NeedHelp from '/snippets/need-help.mdx'; - - - **Prerequisites**: Completed the [Deploy Your First Agent](/tutorials/deploy-your-first-agent) tutorial - - -## What You'll Build - -In this tutorial, you'll create an internal Q&A agent that: -- Answers questions about your company's internal processes -- Provides instant access to team knowledge -- Integrates with your existing documentation -- Can be embedded in Slack, Teams, or web applications - -## The Internal Knowledge Challenge - -Every organization struggles with knowledge management: -- **Scattered information**: Docs in different systems and formats -- **Expertise silos**: Knowledge locked in individual team members -- **Onboarding friction**: New team members struggle to find answers -- **Consistent responses**: Ensuring everyone gets the same accurate information - -RunAgent solves this by creating a centralized, AI-powered knowledge interface that can be accessed from anywhere. - -## Step 1: Create Your Q&A Agent - -Let's start by creating a new agent for internal Q&A: - -```bash -runagent init internal-qa --framework custom -cd internal-qa -``` - -## Step 2: Build the Knowledge Base Agent - -Replace `main.py` with a comprehensive Q&A agent: - -```python main.py -from typing import Iterator, Dict, Any, List -import json -from datetime import datetime -import re - -class InternalQAAgent: - def __init__(self): - # Internal knowledge base - in production, this would be a vector database - self.knowledge_base = { - "company_info": { - "name": "RunAgent Inc.", - "founded": "2024", - "mission": "Making AI agent deployment accessible to every developer", - "headquarters": "San Francisco, CA", - "team_size": "15-20 employees" - }, - "policies": { - "remote_work": { - "policy": "We support flexible remote work with core hours 10 AM - 3 PM PST", - "meetings": "All meetings should be scheduled during core hours", - "communication": "Use Slack for async communication, Zoom for meetings" - }, - "vacation": { - "policy": "Unlimited PTO with manager approval", - "notice": "Give at least 2 weeks notice for planned time off", - "blackout": "No vacation during major release periods" - }, - "expenses": { - "policy": "All business expenses must be pre-approved", - "limit": "Meals under $50, travel requires manager approval", - "reimbursement": "Submit receipts within 30 days" - } - }, - "technical": { - "deployment": { - "staging": "Deploy to staging environment first", - "production": "Production deployments require code review and tests", - "rollback": "Always have a rollback plan ready" - }, - "code_review": { - "policy": "All code must be reviewed by at least one team member", - "requirements": "Pass all tests and linting checks", - "approval": "Requires approval from code owner" - }, - "security": { - "secrets": "Never commit secrets to version control", - "api_keys": "Use environment variables for all API keys", - "access": "Follow principle of least privilege" - } - }, - "tools": { - "development": ["VS Code", "Git", "Docker", "Python 3.8+"], - "communication": ["Slack", "Zoom", "Notion", "GitHub"], - "monitoring": ["DataDog", "Sentry", "CloudWatch"], - "deployment": ["AWS", "Docker", "Kubernetes", "Terraform"] - }, - "contacts": { - "hr": "hr@runagent.ai", - "it": "it@runagent.ai", - "security": "security@runagent.ai", - "legal": "legal@runagent.ai" - } - } - - def search_knowledge(self, query: str, category: str = None) -> List[Dict[str, Any]]: - """Search the knowledge base for relevant information""" - query_lower = query.lower() - results = [] - - # Define search categories - categories = { - "company": ["company_info"], - "policies": ["policies"], - "technical": ["technical"], - "tools": ["tools"], - "contacts": ["contacts"] - } - - # Determine search scope - search_scope = categories.get(category, self.knowledge_base.keys()) if category else self.knowledge_base.keys() - - for scope in search_scope: - if scope in self.knowledge_base: - scope_data = self.knowledge_base[scope] - matches = self._find_matches(scope_data, query_lower, scope) - results.extend(matches) - - # Sort by relevance (simple keyword matching) - results.sort(key=lambda x: x.get('relevance', 0), reverse=True) - return results[:5] # Return top 5 results - - def _find_matches(self, data: Any, query: str, category: str) -> List[Dict[str, Any]]: - """Find matches in a specific category of data""" - matches = [] - - if isinstance(data, dict): - for key, value in data.items(): - # Check if key matches - if query in key.lower(): - matches.append({ - "category": category, - "key": key, - "value": str(value), - "relevance": 2 - }) - - # Check if value matches - if isinstance(value, (str, list)): - if query in str(value).lower(): - matches.append({ - "category": category, - "key": key, - "value": str(value), - "relevance": 1 - }) - - # Recursively search nested structures - if isinstance(value, (dict, list)): - nested_matches = self._find_matches(value, query, category) - matches.extend(nested_matches) - - elif isinstance(data, list): - for i, item in enumerate(data): - if query in str(item).lower(): - matches.append({ - "category": category, - "key": f"item_{i}", - "value": str(item), - "relevance": 1 - }) - - return matches - - def generate_answer(self, query: str, context: List[Dict[str, Any]]) -> str: - """Generate a comprehensive answer based on context""" - if not context: - return "I couldn't find relevant information for your question. Please try rephrasing or contact the appropriate team member." - - answer_parts = [] - - # Group by category - by_category = {} - for item in context: - cat = item['category'] - if cat not in by_category: - by_category[cat] = [] - by_category[cat].append(item) - - # Build answer - for category, items in by_category.items(): - answer_parts.append(f"**{category.title()} Information:**") - - for item in items: - if item['key'] != item['value']: # Not a simple key-value pair - answer_parts.append(f"β€’ **{item['key']}**: {item['value']}") - else: - answer_parts.append(f"β€’ {item['value']}") - - answer_parts.append("") # Empty line between categories - - # Add contact information if relevant - if any("contact" in item['category'] for item in context): - answer_parts.append("**Need more help?** Contact the appropriate team member listed above.") - - return "\n".join(answer_parts) - -def ask_question_sync(question: str, category: str = None, user: str = "anonymous") -> Dict[str, Any]: - """Synchronous Q&A response""" - agent = InternalQAAgent() - - # Search for relevant information - results = agent.search_knowledge(question, category) - - # Generate answer - answer = agent.generate_answer(question, results) - - return { - "question": question, - "answer": answer, - "category": category, - "user": user, - "timestamp": datetime.now().isoformat(), - "sources": len(results), - "confidence": "high" if results else "low" - } - -def ask_question_stream(question: str, category: str = None, user: str = "anonymous") -> Iterator[str]: - """Streaming Q&A response""" - agent = InternalQAAgent() - - yield f"πŸ” Searching for information about: {question}\n\n" - - # Search for relevant information - results = agent.search_knowledge(question, category) - - if not results: - yield "❌ I couldn't find relevant information for your question.\n" - yield "πŸ’‘ Try rephrasing your question or contact the appropriate team member.\n" - return - - yield f"βœ… Found {len(results)} relevant information sources.\n\n" - - # Generate and stream answer - answer = agent.generate_answer(question, results) - - # Stream the answer with typing effect - for line in answer.split('\n'): - if line.strip(): - yield line + '\n' - else: - yield '\n' - - yield f"\nπŸ“š Based on {len(results)} sources from our knowledge base.\n" - -def get_available_categories() -> Dict[str, Any]: - """Get available question categories""" - agent = InternalQAAgent() - return { - "categories": [ - {"name": "company", "description": "Company information and general questions"}, - {"name": "policies", "description": "HR policies, vacation, expenses"}, - {"name": "technical", "description": "Development processes and technical guidelines"}, - {"name": "tools", "description": "Tools and software used by the team"}, - {"name": "contacts", "description": "Team contacts and who to reach out to"} - ], - "total_categories": 5, - "last_updated": datetime.now().isoformat() - } - -def suggest_questions(category: str = None) -> Dict[str, Any]: - """Suggest common questions for a category""" - suggestions = { - "company": [ - "What is our company mission?", - "When was the company founded?", - "How many employees do we have?", - "Where is our headquarters?" - ], - "policies": [ - "What is our remote work policy?", - "How much vacation time do I get?", - "What is the expense reimbursement policy?", - "What are our core working hours?" - ], - "technical": [ - "What is our deployment process?", - "What are our code review requirements?", - "How do we handle security?", - "What testing is required before deployment?" - ], - "tools": [ - "What development tools do we use?", - "What communication tools are available?", - "How do I access our monitoring systems?", - "What deployment tools are we using?" - ], - "contacts": [ - "Who should I contact for HR questions?", - "How do I reach the IT team?", - "Who handles security issues?", - "Who can I talk to about legal matters?" - ] - } - - if category and category in suggestions: - return { - "category": category, - "suggestions": suggestions[category], - "total": len(suggestions[category]) - } - else: - return { - "all_categories": suggestions, - "total_suggestions": sum(len(v) for v in suggestions.values()) - } -``` - -## Step 3: Configure Your Agent - -Update `runagent.config.json`: - -```json -{ - "agent_name": "internal-qa", - "description": "Internal Q&A agent for team knowledge", - "framework": "custom", - "agent_architecture": { - "entrypoints": [ - { - "file": "main.py", - "module": "ask_question_sync", - "tag": "ask" - }, - { - "file": "main.py", - "module": "ask_question_stream", - "tag": "ask_stream" - }, - { - "file": "main.py", - "module": "get_available_categories", - "tag": "categories" - }, - { - "file": "main.py", - "module": "suggest_questions", - "tag": "suggest" - } - ] - } -} -``` - -## Step 4: Deploy Your Q&A Agent - -Start your internal Q&A agent: - -```bash -runagent serve . -``` - -## Step 5: Test Your Q&A Agent - -### Test Basic Questions - -```python -from runagent import RunAgentClient - -# Connect to your Q&A agent -qa = RunAgentClient( - agent_id="your_agent_id_here", # Replace with actual ID - entrypoint_tag="ask", - local=True -) - -# Test different types of questions -questions = [ - "What is our remote work policy?", - "What development tools do we use?", - "Who should I contact for HR questions?", - "What is our deployment process?", - "How much vacation time do I get?" -] - -for question in questions: - print(f"\nQ: {question}") - response = qa.run(question=question, user="test_user") - print(f"A: {response['answer']}") - print(f"Sources: {response['sources']}, Confidence: {response['confidence']}") -``` - -### Test Category-Specific Questions - -```python -# Test category-specific questions -category_questions = { - "policies": "What is our expense reimbursement policy?", - "technical": "What are our code review requirements?", - "tools": "What monitoring tools do we use?", - "company": "What is our company mission?" -} - -for category, question in category_questions.items(): - print(f"\n[{category.upper()}] Q: {question}") - response = qa.run(question=question, category=category, user="test_user") - print(f"A: {response['answer']}") -``` - -### Test Streaming Responses - -```python -# Test streaming for better user experience -qa_stream = RunAgentClient( - agent_id="your_agent_id_here", - entrypoint_tag="ask_stream", - local=True -) - -print("Streaming Q&A:") -for chunk in qa_stream.run(question="What is our remote work policy?", user="test_user"): - print(chunk, end="", flush=True) -``` - -## Step 6: Build a Web Interface - -Create a web interface for your internal Q&A system: - -```html qa_interface.html - - - - Internal Q&A System - - - -
-

πŸ€– Internal Q&A System

-

Ask questions about company policies, technical processes, tools, and more!

-
- -
- - - -
- -
-
All
-
Company
-
Policies
-
Technical
-
Tools
-
Contacts
-
- -
-
- - - - -``` - -## Step 7: Test the Web Interface - -1. Open `qa_interface.html` in your browser -2. Try asking questions like: - - "What is our remote work policy?" - - "What development tools do we use?" - - "Who should I contact for HR questions?" -3. Use the category filters to narrow down your search -4. Click on suggested questions to try them out - -## What You've Accomplished - -You've built a comprehensive internal Q&A system: - - - - Created a centralized knowledge base for team information - - - Implemented intelligent search across different categories - - - Built a user-friendly web interface for easy access - - - Added question suggestions to help users discover information - - - -## Advanced Features - -### 1. **Integration with Slack** - -Create a Slack bot that uses your Q&A agent: - -```python slack_bot.py -import os -from slack_sdk import WebClient -from slack_sdk.errors import SlackApiError -from runagent import RunAgentClient - -# Initialize Slack client -slack_client = WebClient(token=os.environ["SLACK_BOT_TOKEN"]) - -# Initialize Q&A agent -qa_agent = RunAgentClient( - agent_id="your_agent_id_here", - entrypoint_tag="ask", - local=True -) - -def handle_message(event): - """Handle incoming Slack messages""" - text = event.get('text', '') - if text.startswith('!qa '): - question = text[4:] # Remove '!qa ' prefix - - # Get answer from Q&A agent - response = qa_agent.run(question=question, user=event['user']) - - # Send answer back to Slack - slack_client.chat_postMessage( - channel=event['channel'], - text=f"πŸ€– *Q&A Response:*\n{response['answer']}" - ) -``` - -### 2. **Integration with Microsoft Teams** - -Create a Teams webhook that uses your Q&A agent: - -```python teams_webhook.py -import json -import requests -from runagent import RunAgentClient - -qa_agent = RunAgentClient( - agent_id="your_agent_id_here", - entrypoint_tag="ask", - local=True -) - -def handle_teams_message(question, user): - """Handle Teams webhook messages""" - response = qa_agent.run(question=question, user=user) - - # Format response for Teams - teams_message = { - "type": "message", - "text": f"πŸ€– **Q&A Response:**\n\n{response['answer']}\n\n*Sources: {response['sources']} | Confidence: {response['confidence']}*" - } - - return teams_message -``` - -### 3. **Knowledge Base Updates** - -Add functionality to update the knowledge base: - -```python -def update_knowledge_base(category: str, key: str, value: str) -> Dict[str, Any]: - """Update the knowledge base with new information""" - # In production, this would update a database - # For now, we'll just return a success message - - return { - "status": "success", - "message": f"Updated {category}.{key}", - "timestamp": datetime.now().isoformat() - } -``` - -## Production Considerations - -### 1. **Database Integration** -Replace the in-memory knowledge base with a real database: - -```python -import sqlite3 -import json - -class DatabaseKnowledgeBase: - def __init__(self, db_path="knowledge.db"): - self.conn = sqlite3.connect(db_path) - self.create_tables() - - def create_tables(self): - self.conn.execute(""" - CREATE TABLE IF NOT EXISTS knowledge ( - id INTEGER PRIMARY KEY, - category TEXT, - key TEXT, - value TEXT, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - ) - """) - self.conn.commit() - - def search(self, query: str, category: str = None): - # Implement database search - pass -``` - -### 2. **Vector Search** -For better search results, integrate with a vector database: - -```python -import chromadb - -class VectorKnowledgeBase: - def __init__(self): - self.client = chromadb.Client() - self.collection = self.client.create_collection("knowledge") - - def add_document(self, text: str, metadata: dict): - self.collection.add( - documents=[text], - metadatas=[metadata], - ids=[f"doc_{len(self.collection.get()['ids'])}"] - ) - - def search(self, query: str, n_results: int = 5): - results = self.collection.query( - query_texts=[query], - n_results=n_results - ) - return results -``` - -### 3. **Analytics and Monitoring** -Track usage and improve the system: - -```python -def log_question(question: str, answer: str, user: str, confidence: str): - """Log questions for analytics""" - # In production, send to analytics service - print(f"Q&A Log: {user} asked '{question}' -> confidence: {confidence}") -``` - -## Next Steps - - - - Learn how to integrate with Slack and other communication tools - - - Connect to real databases for dynamic knowledge management - - - Implement semantic search for better results - - - Add analytics and monitoring to track usage - - - - -**πŸŽ‰ Excellent work!** You've built a production-ready internal Q&A system that can centralize your team's knowledge and make it accessible from anywhere. This is a powerful tool for improving team productivity and knowledge sharing! - - - diff --git a/docs/tutorials/lead-agent.mdx b/docs/tutorials/lead-agent.mdx new file mode 100644 index 0000000..3deee82 --- /dev/null +++ b/docs/tutorials/lead-agent.mdx @@ -0,0 +1,308 @@ +--- +title: 'Lead Scoring Agent' +description: 'Build an AI-powered lead scoring system with automated email generation' +icon: 'chart-line' +--- + +import NeedHelp from '/snippets/need-help.mdx'; + + + **Prerequisites**: Completed the [Deploy Your First Agent](/tutorials/deploy-your-first-agent) tutorial + + +## What You'll Build + +In this tutorial, you'll create a lead scoring agent that: +- Scores candidates based on job descriptions using AI +- Ranks leads automatically with intelligent analysis +- Generates personalized emails for top candidates +- Provides a complete SaaS solution with frontend and backend +- Uses CrewAI flows for multi-agent orchestration + +## The Lead Scoring Challenge + +Recruiting and lead qualification is time-consuming: +- **Manual screening**: Reviewing hundreds of resumes manually +- **Inconsistent scoring**: Different recruiters score differently +- **Email personalization**: Writing personalized emails takes hours +- **Scalability**: Hard to scale manual processes + +RunAgent solves this by automating the entire lead scoring workflow with AI agents that can analyze, score, and communicate with candidates. + +## Architecture Overview + +The lead scoring agent uses a multi-layered architecture: + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ React Frontend β”‚ +β”‚ (Port 5173) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ HTTP REST API + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Flask Backend β”‚ +β”‚ (Port 8000) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ RunAgent Python SDK + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ RunAgent Agent β”‚ +β”‚ (CrewAI Flow) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +## Step 1: Understanding the Agent Structure + +The lead scoring agent uses CrewAI flows to orchestrate multiple AI agents: + +**Key Components:** +- **LeadDataCollectionCrew**: Collects and validates lead data +- **LeadAnalysisCrew**: Analyzes candidate profiles +- **LeadScoringCrew**: Scores candidates based on job requirements +- **EmailGenerationCrew**: Creates personalized emails + +**Entrypoints:** +- `lead_score_flow`: Main flow that orchestrates the entire process +- `score_candidate`: Score a single candidate + +## Step 2: Agent Configuration + +The agent is configured using `runagent.config.json`: + +```json +{ + "agent_name": "lead-scoring", + "description": "AI-powered lead scoring with email generation", + "framework": "crewai", + "agent_architecture": { + "entrypoints": [ + { + "file": "main.py", + "module": "lead_score_flow", + "tag": "lead_score_flow" + }, + { + "file": "main.py", + "module": "score_candidate", + "tag": "score_candidate" + } + ] + } +} +``` + +## Step 3: Core Agent Logic (Gist) + +The agent processes candidates through multiple stages: + +```python +# Simplified flow structure +def lead_score_flow( + candidates: List[Dict], + job_description: str, + top_n: int = 3, + generate_emails: bool = True, + additional_instructions: str = "" +) -> Dict[str, Any]: + """ + Main flow that: + 1. Collects and validates candidate data + 2. Analyzes each candidate's profile + 3. Scores candidates based on job requirements + 4. Ranks candidates and selects top N + 5. Generates personalized emails + """ + # Data collection + validated_candidates = collect_lead_data(candidates) + + # Analysis and scoring + scored_candidates = score_leads( + validated_candidates, + job_description, + additional_instructions + ) + + # Ranking + top_candidates = rank_candidates(scored_candidates, top_n) + + # Email generation + if generate_emails: + emails = generate_emails(top_candidates, job_description) + return { + "scored_candidates": scored_candidates, + "top_candidates": top_candidates, + "emails": emails + } + + return { + "scored_candidates": scored_candidates, + "top_candidates": top_candidates + } +``` + +## Step 4: Backend Integration + +The Flask backend provides REST API endpoints: + +```python +# Backend API structure +@app.route('/api/score-leads', methods=['POST']) +def score_leads(): + """ + Endpoint that: + - Receives candidates and job description + - Calls RunAgent agent + - Returns scored results + """ + client = RunAgentClient( + agent_id=agent_id, + entrypoint_tag="lead_score_flow", + local=False + ) + + result = client.run( + candidates=candidates, + job_description=job_description, + top_n=top_n, + generate_emails=generate_emails + ) + + return jsonify(result) +``` + +## Step 5: Frontend Integration + +The React frontend provides a user-friendly interface: + +**Key Features:** +- CSV upload for candidate data +- Job description input +- Real-time scoring results +- Email preview and download +- Top candidates visualization + +## Step 6: Deployment + +### Local Deployment + +```bash +# 1. Deploy the RunAgent agent +cd examples/lead-agent/lead-score-flow +runagent serve . + +# 2. Start the backend +cd ../backend +python app.py + +# 3. Start the frontend +cd ../frontend +npm run dev +``` + +### Production Deployment + +The agent can be deployed to RunAgent Cloud: + +```bash +runagent deploy . +``` + +## What You've Accomplished + +You've built a complete lead scoring SaaS solution: + + + + Automated candidate scoring using multi-agent AI workflows + + + Automatic ranking of candidates based on job fit + + + Personalized email generation for top candidates + + + Complete SaaS application with frontend and backend + + + +## Key Features + +### Multi-Agent Orchestration +- Uses CrewAI flows to coordinate multiple specialized agents +- Each agent handles a specific aspect of the scoring process +- Parallel processing for efficient candidate evaluation + +### Intelligent Scoring +- Analyzes candidate profiles against job requirements +- Considers skills, experience, and cultural fit +- Provides detailed scoring breakdowns + +### Email Personalization +- Generates context-aware emails for each candidate +- Incorporates specific candidate details +- Maintains professional tone and structure + +## Example Usage + +```python +from runagent import RunAgentClient + +client = RunAgentClient( + agent_id="your_agent_id", + entrypoint_tag="lead_score_flow", + local=False +) + +result = client.run( + candidates=[ + { + "id": 1, + "name": "John Doe", + "email": "john@example.com", + "bio": "Experienced React developer", + "skills": "React, Node.js, TypeScript" + } + ], + job_description="Looking for a senior React developer...", + top_n=3, + generate_emails=True +) +``` + +## Next Steps + + + + Customize scoring criteria and weights + + + Add features like candidate tracking and analytics + + + Deploy to production with proper scaling + + + Explore the complete example code + + + +## Repository + +View the complete example code and documentation: + +**Repository**: [https://github.com/runagent-dev/runagent/tree/main/examples/lead-agent](https://github.com/runagent-dev/runagent/tree/main/examples/lead-agent) + +The repository includes: +- Complete agent implementation with CrewAI flows +- Flask backend API +- React frontend application +- Deployment guides and documentation +- Example CSV files and test data + + +**πŸŽ‰ Great job!** You've learned how to build a production-ready lead scoring system using RunAgent and CrewAI. This demonstrates the power of multi-agent orchestration for complex business workflows! + + + diff --git a/docs/tutorials/multi-language-wrapper.mdx b/docs/tutorials/multi-language-wrapper.mdx deleted file mode 100644 index e97a257..0000000 --- a/docs/tutorials/multi-language-wrapper.mdx +++ /dev/null @@ -1,642 +0,0 @@ ---- -title: 'Multi-Language Wrapper' -description: 'Deploy a Python agent and call it from multiple programming languages' -icon: 'globe' ---- - -import NeedHelp from '/snippets/need-help.mdx'; - - - **Prerequisites**: Completed the [Deploy Your First Agent](/tutorials/deploy-your-first-agent) tutorial - - -## What You'll Build - -In this tutorial, you'll create a Python agent and demonstrate how to call it from: -- **Python** (native SDK) -- **JavaScript** (Node.js and browser) -- **Rust** (high-performance systems) -- **Go** (concurrent applications) - -This showcases RunAgent's core value proposition: write once in Python, use everywhere. - -## The Multi-Language Challenge - -Traditional AI agent deployment requires: -- **Language-specific implementations** for each target language -- **API design and maintenance** across multiple interfaces -- **Consistent behavior** across different language bindings -- **Real-time streaming** support in each language - -RunAgent eliminates all of this complexity by automatically generating native-feeling SDKs for every supported language. - -## Step 1: Create Your Multi-Language Agent - -Let's build a data analysis agent that can be called from any language: - -```bash -runagent init data-analyzer --framework custom -cd data-analyzer -``` - -## Step 2: Build the Data Analysis Agent - -Replace `main.py` with a comprehensive data analysis agent: - -```python main.py -from typing import Iterator, Dict, Any, List -import json -import statistics -from datetime import datetime - -class DataAnalyzer: - def __init__(self): - self.supported_formats = ["json", "csv", "xml"] - self.analysis_types = ["summary", "trends", "outliers", "correlations"] - - def analyze_data(self, data: List[Dict], analysis_type: str = "summary") -> Dict[str, Any]: - """Analyze a dataset and return insights""" - if not data: - return {"error": "No data provided for analysis"} - - # Extract numeric fields - numeric_fields = {} - for item in data: - for key, value in item.items(): - if isinstance(value, (int, float)): - if key not in numeric_fields: - numeric_fields[key] = [] - numeric_fields[key].append(value) - - result = { - "analysis_type": analysis_type, - "total_records": len(data), - "numeric_fields": list(numeric_fields.keys()), - "timestamp": datetime.now().isoformat() - } - - if analysis_type == "summary": - result["summary"] = self._generate_summary(numeric_fields) - elif analysis_type == "trends": - result["trends"] = self._analyze_trends(numeric_fields) - elif analysis_type == "outliers": - result["outliers"] = self._find_outliers(numeric_fields) - elif analysis_type == "correlations": - result["correlations"] = self._find_correlations(numeric_fields) - - return result - - def _generate_summary(self, numeric_fields: Dict[str, List[float]]) -> Dict[str, Any]: - """Generate statistical summary for numeric fields""" - summary = {} - for field, values in numeric_fields.items(): - summary[field] = { - "count": len(values), - "mean": round(statistics.mean(values), 2), - "median": round(statistics.median(values), 2), - "min": min(values), - "max": max(values), - "std_dev": round(statistics.stdev(values) if len(values) > 1 else 0, 2) - } - return summary - - def _analyze_trends(self, numeric_fields: Dict[str, List[float]]) -> Dict[str, str]: - """Analyze trends in numeric data""" - trends = {} - for field, values in numeric_fields.items(): - if len(values) < 2: - trends[field] = "Insufficient data for trend analysis" - continue - - # Simple trend analysis - first_half = values[:len(values)//2] - second_half = values[len(values)//2:] - - first_avg = statistics.mean(first_half) - second_avg = statistics.mean(second_half) - - if second_avg > first_avg * 1.1: - trends[field] = "Increasing trend" - elif second_avg < first_avg * 0.9: - trends[field] = "Decreasing trend" - else: - trends[field] = "Stable trend" - - return trends - - def _find_outliers(self, numeric_fields: Dict[str, List[float]]) -> Dict[str, List[float]]: - """Find outliers using IQR method""" - outliers = {} - for field, values in numeric_fields.items(): - if len(values) < 4: - outliers[field] = [] - continue - - q1 = statistics.quantiles(values, n=4)[0] - q3 = statistics.quantiles(values, n=4)[2] - iqr = q3 - q1 - - lower_bound = q1 - 1.5 * iqr - upper_bound = q3 + 1.5 * iqr - - field_outliers = [v for v in values if v < lower_bound or v > upper_bound] - outliers[field] = field_outliers - - return outliers - - def _find_correlations(self, numeric_fields: Dict[str, List[float]]) -> Dict[str, float]: - """Find correlations between numeric fields""" - correlations = {} - field_names = list(numeric_fields.keys()) - - for i, field1 in enumerate(field_names): - for field2 in field_names[i+1:]: - values1 = numeric_fields[field1] - values2 = numeric_fields[field2] - - if len(values1) == len(values2) and len(values1) > 1: - try: - corr = statistics.correlation(values1, values2) - correlations[f"{field1}_vs_{field2}"] = round(corr, 3) - except: - correlations[f"{field1}_vs_{field2}"] = 0.0 - - return correlations - -def analyze_data_sync(data: List[Dict], analysis_type: str = "summary") -> Dict[str, Any]: - """Synchronous data analysis""" - analyzer = DataAnalyzer() - return analyzer.analyze_data(data, analysis_type) - -def analyze_data_stream(data: List[Dict], analysis_type: str = "summary") -> Iterator[str]: - """Streaming data analysis with progress updates""" - analyzer = DataAnalyzer() - - yield f"πŸ” Starting {analysis_type} analysis of {len(data)} records...\n\n" - - if analysis_type == "summary": - yield "πŸ“Š Generating statistical summary...\n" - result = analyzer.analyze_data(data, analysis_type) - - yield f"πŸ“ˆ Found {len(result['numeric_fields'])} numeric fields: {', '.join(result['numeric_fields'])}\n\n" - - for field, stats in result['summary'].items(): - yield f"**{field}**:\n" - yield f" β€’ Count: {stats['count']}\n" - yield f" β€’ Mean: {stats['mean']}\n" - yield f" β€’ Median: {stats['median']}\n" - yield f" β€’ Range: {stats['min']} - {stats['max']}\n" - yield f" β€’ Std Dev: {stats['std_dev']}\n\n" - - elif analysis_type == "trends": - yield "πŸ“ˆ Analyzing trends...\n" - result = analyzer.analyze_data(data, analysis_type) - - for field, trend in result['trends'].items(): - yield f"**{field}**: {trend}\n" - - elif analysis_type == "outliers": - yield "🎯 Detecting outliers...\n" - result = analyzer.analyze_data(data, analysis_type) - - for field, outliers in result['outliers'].items(): - if outliers: - yield f"**{field}**: Found {len(outliers)} outliers: {outliers}\n" - else: - yield f"**{field}**: No outliers detected\n" - - elif analysis_type == "correlations": - yield "πŸ”— Finding correlations...\n" - result = analyzer.analyze_data(data, analysis_type) - - for pair, corr in result['correlations'].items(): - yield f"**{pair}**: {corr}\n" - - yield f"\nβœ… Analysis complete! Processed {len(data)} records.\n" - -def get_analysis_capabilities() -> Dict[str, Any]: - """Get information about analysis capabilities""" - analyzer = DataAnalyzer() - return { - "supported_formats": analyzer.supported_formats, - "analysis_types": analyzer.analysis_types, - "description": "Advanced data analysis agent with statistical insights", - "version": "1.0.0" - } -``` - -## Step 3: Configure Your Agent - -Update `runagent.config.json`: - -```json -{ - "agent_name": "data-analyzer", - "description": "Multi-language data analysis agent", - "framework": "custom", - "agent_architecture": { - "entrypoints": [ - { - "file": "main.py", - "module": "analyze_data_sync", - "tag": "analyze" - }, - { - "file": "main.py", - "module": "analyze_data_stream", - "tag": "analyze_stream" - }, - { - "file": "main.py", - "module": "get_analysis_capabilities", - "tag": "capabilities" - } - ] - } -} -``` - -## Step 4: Deploy Your Agent - -Start your data analysis agent: - -```bash -runagent serve . -``` - -Note the agent ID for the next steps. - -## Step 5: Call from Python (Native) - -Create a Python client script: - -```python python_client.py -from runagent import RunAgentClient -import json - -# Sample data for analysis -sample_data = [ - {"sales": 1000, "profit": 200, "region": "North"}, - {"sales": 1500, "profit": 300, "region": "South"}, - {"sales": 1200, "profit": 250, "region": "East"}, - {"sales": 1800, "profit": 400, "region": "West"}, - {"sales": 900, "profit": 150, "region": "North"} -] - -# Connect to your agent -client = RunAgentClient( - agent_id="your_agent_id_here", # Replace with actual ID - entrypoint_tag="analyze", - local=True -) - -# Test different analysis types -analysis_types = ["summary", "trends", "outliers", "correlations"] - -for analysis_type in analysis_types: - print(f"\n=== {analysis_type.upper()} ANALYSIS ===") - result = client.run(data=sample_data, analysis_type=analysis_type) - print(json.dumps(result, indent=2)) - -# Test streaming -print("\n=== STREAMING ANALYSIS ===") -stream_client = RunAgentClient( - agent_id="your_agent_id_here", - entrypoint_tag="analyze_stream", - local=True -) - -for chunk in stream_client.run(data=sample_data, analysis_type="summary"): - print(chunk, end="", flush=True) -``` - -## Step 6: Call from JavaScript (Node.js) - -Create a JavaScript client: - -```javascript javascript_client.js -// First install: npm install runagent -const { RunAgentClient } = require('runagent'); - -const sampleData = [ - { sales: 1000, profit: 200, region: "North" }, - { sales: 1500, profit: 300, region: "South" }, - { sales: 1200, profit: 250, region: "East" }, - { sales: 1800, profit: 400, region: "West" }, - { sales: 900, profit: 150, region: "North" } -]; - -async function testAnalysis() { - // Connect to your agent - const client = new RunAgentClient({ - agentId: "your_agent_id_here", // Replace with actual ID - entrypointTag: "analyze", - local: true - }); - - await client.initialize(); - - // Test different analysis types - const analysisTypes = ["summary", "trends", "outliers", "correlations"]; - - for (const analysisType of analysisTypes) { - console.log(`\n=== ${analysisType.toUpperCase()} ANALYSIS ===`); - const result = await client.run({ - data: sampleData, - analysis_type: analysisType - }); - console.log(JSON.stringify(result, null, 2)); - } - - // Test streaming - console.log("\n=== STREAMING ANALYSIS ==="); - const streamClient = new RunAgentClient({ - agentId: "your_agent_id_here", - entrypointTag: "analyze_stream", - local: true - }); - - await streamClient.initialize(); - - const stream = await streamClient.run({ - data: sampleData, - analysis_type: "summary" - }); - - for await (const chunk of stream) { - process.stdout.write(chunk); - } -} - -testAnalysis().catch(console.error); -``` - -## Step 7: Call from Rust - -Create a Rust client: - -```rust rust_client.rs -use runagent::client::RunAgentClient; -use serde_json::json; -use futures::StreamExt; - -#[tokio::main] -async fn main() -> Result<(), Box> { - let sample_data = json!([ - {"sales": 1000, "profit": 200, "region": "North"}, - {"sales": 1500, "profit": 300, "region": "South"}, - {"sales": 1200, "profit": 250, "region": "East"}, - {"sales": 1800, "profit": 400, "region": "West"}, - {"sales": 900, "profit": 150, "region": "North"} - ]); - - // Connect to your agent - let client = RunAgentClient::new("your_agent_id_here", "analyze", true).await?; - - // Test different analysis types - let analysis_types = vec!["summary", "trends", "outliers", "correlations"]; - - for analysis_type in analysis_types { - println!("\n=== {} ANALYSIS ===", analysis_type.to_uppercase()); - - let result = client.run(&[ - ("data", sample_data.clone()), - ("analysis_type", json!(analysis_type)) - ]).await?; - - println!("{}", serde_json::to_string_pretty(&result)?); - } - - // Test streaming - println!("\n=== STREAMING ANALYSIS ==="); - let stream_client = RunAgentClient::new("your_agent_id_here", "analyze_stream", true).await?; - - let mut stream = stream_client.run_stream(&[ - ("data", sample_data), - ("analysis_type", json!("summary")) - ]).await?; - - while let Some(chunk) = stream.next().await { - print!("{}", chunk?); - } - - Ok(()) -} -``` - -## Step 8: Call from Go - -Create a Go client: - -```go go_client.go -package main - -import ( - "context" - "fmt" - "log" - "time" - "github.com/runagent-dev/runagent-go/pkg/client" -) - -func main() { - sampleData := []map[string]interface{}{ - {"sales": 1000, "profit": 200, "region": "North"}, - {"sales": 1500, "profit": 300, "region": "South"}, - {"sales": 1200, "profit": 250, "region": "East"}, - {"sales": 1800, "profit": 400, "region": "West"}, - {"sales": 900, "profit": 150, "region": "North"}, - } - - // Connect to your agent - c, err := client.NewWithAddress( - "your_agent_id_here", // Replace with actual ID - "analyze", - true, - "localhost", - 8451, - ) - if err != nil { - log.Fatal(err) - } - defer c.Close() - - ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) - defer cancel() - - // Test different analysis types - analysisTypes := []string{"summary", "trends", "outliers", "correlations"} - - for _, analysisType := range analysisTypes { - fmt.Printf("\n=== %s ANALYSIS ===\n", analysisType) - - result, err := c.Run(ctx, map[string]interface{}{ - "data": sampleData, - "analysis_type": analysisType, - }) - if err != nil { - log.Printf("Error: %v", err) - continue - } - - fmt.Printf("%+v\n", result) - } - - // Test streaming - fmt.Println("\n=== STREAMING ANALYSIS ===") - streamClient, err := client.NewWithAddress( - "your_agent_id_here", - "analyze_stream", - true, - "localhost", - 8451, - ) - if err != nil { - log.Fatal(err) - } - defer streamClient.Close() - - s, err := streamClient.RunStream(ctx, map[string]interface{}{ - "data": sampleData, - "analysis_type": "summary", - }) - if err != nil { - log.Fatal(err) - } - defer s.Close() - - for { - data, hasMore, err := s.Next(ctx) - if err != nil { - log.Fatal(err) - } - if !hasMore { - break - } - fmt.Print(data) - } -} -``` - -## Step 9: Test All Languages - -Run each client to see the same Python agent working across all languages: - -```bash -# Python -python python_client.py - -# JavaScript (after npm install runagent) -node javascript_client.js - -# Rust (after cargo add runagent tokio) -cargo run - -# Go (after go mod init && go get github.com/runagent-dev/runagent-go) -go run go_client.go -``` - -## What You've Accomplished - -You've demonstrated RunAgent's core value proposition: - - - - Built a sophisticated data analysis agent in Python - - - Called the same agent from 4 different programming languages - - - Each language gets native-feeling APIs and performance characteristics - - - Streaming works seamlessly across all language boundaries - - - -## Key Insights - -### 1. **Consistent API Design** -All languages receive the same function signature: -- `data`: List of dictionaries for analysis -- `analysis_type`: String specifying the type of analysis - -### 2. **Language-Specific Idioms** -Each SDK adapts to language conventions: -- **Python**: Dictionary parameters, native iteration -- **JavaScript**: Object parameters, async/await -- **Rust**: Array parameters, futures streams -- **Go**: Map parameters, context-aware operations - -### 3. **Automatic Serialization** -RunAgent handles all the complex serialization/deserialization automatically. - -### 4. **Streaming Everywhere** -The same streaming function works identically across all languages. - -## Production Considerations - -### Error Handling -Each SDK provides language-appropriate error handling: - -```python -# Python -try: - result = client.run(data=data, analysis_type="summary") -except RunAgentError as e: - print(f"Analysis failed: {e}") -``` - -```javascript -// JavaScript -try { - const result = await client.run({data, analysis_type: "summary"}); -} catch (error) { - console.error("Analysis failed:", error.message); -} -``` - -### Performance Optimization -- **Python**: Use async client for concurrent requests -- **JavaScript**: Use connection pooling for multiple requests -- **Rust**: Leverage zero-copy deserialization -- **Go**: Use goroutines for concurrent processing - -### Monitoring and Logging -Add logging to track usage across languages: - -```python -def analyze_data_sync(data: List[Dict], analysis_type: str = "summary") -> Dict[str, Any]: - # Add logging - print(f"Analysis request: {analysis_type}, {len(data)} records") - - analyzer = DataAnalyzer() - result = analyzer.analyze_data(data, analysis_type) - - print(f"Analysis complete: {result['total_records']} records processed") - return result -``` - -## Next Steps - - - - Learn advanced integration patterns and best practices - - - Deploy your multi-language agent to production - - - Integrate with advanced AI frameworks - - - Optimize performance across all languages - - - - -**πŸŽ‰ Congratulations!** You've successfully demonstrated RunAgent's core value: write sophisticated AI agents in Python and use them from any programming language with native-feeling APIs. This is the future of AI development! - - - diff --git a/docs/tutorials/overview.mdx b/docs/tutorials/overview.mdx index 47c5970..597aa8d 100644 --- a/docs/tutorials/overview.mdx +++ b/docs/tutorials/overview.mdx @@ -25,9 +25,9 @@ New to RunAgent? Start with the **5-minute** path, then pick a real use-case. ## Real use-cases - - - + + + diff --git a/docs/tutorials/recipe-creator.mdx b/docs/tutorials/recipe-creator.mdx new file mode 100644 index 0000000..d83b5c0 --- /dev/null +++ b/docs/tutorials/recipe-creator.mdx @@ -0,0 +1,392 @@ +--- +title: 'Recipe Creator Agent' +description: 'Build an AI agent that creates personalized recipes based on available ingredients' +icon: 'utensils' +--- + +import NeedHelp from '/snippets/need-help.mdx'; + + + **Prerequisites**: Completed the [Deploy Your First Agent](/tutorials/deploy-your-first-agent) tutorial + + +## What You'll Build + +In this tutorial, you'll create a recipe creator agent that: +- Generates personalized recipes from available ingredients +- Considers dietary restrictions and preferences +- Respects time constraints for meal preparation +- Provides detailed cooking instructions +- Supports both sync and streaming responses + +## The Recipe Creation Challenge + +Creating recipes that match available ingredients is challenging: +- **Ingredient matching**: Finding recipes that use what you have +- **Dietary restrictions**: Accommodating allergies and preferences +- **Time constraints**: Creating recipes that fit your schedule +- **Personalization**: Adapting recipes to individual tastes +- **Instructions**: Providing clear, step-by-step guidance + +RunAgent solves this by creating an intelligent agent that understands context and generates personalized recipes on demand. + +## Architecture Overview + +The recipe creator agent uses a simple but powerful architecture: + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ User Input β”‚ +β”‚ (Ingredients, β”‚ +β”‚ Restrictions, β”‚ +β”‚ Time Limit) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Recipe Agent β”‚ +β”‚ (Generates β”‚ +β”‚ Recipe) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Recipe Output β”‚ +β”‚ (Name, β”‚ +β”‚ Ingredients, β”‚ +β”‚ Instructions) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +## Step 1: Understanding the Agent Structure + +The recipe creator agent provides two entrypoints: + +**Entrypoints:** +- `recipe_create`: Synchronous recipe generation +- `recipe_stream`: Streaming recipe generation for real-time display + +**Key Features:** +- Ingredient-based recipe generation +- Dietary restriction handling +- Time limit consideration +- Detailed cooking instructions +- Nutritional information (optional) + +## Step 2: Agent Configuration + +The agent is configured using `runagent.config.json`: + +```json +{ + "agent_name": "recipe-creator", + "description": "AI-powered recipe generation from ingredients", + "framework": "custom", + "agent_architecture": { + "entrypoints": [ + { + "file": "main.py", + "module": "recipe_create", + "tag": "recipe_create" + }, + { + "file": "main.py", + "module": "recipe_stream", + "tag": "recipe_stream" + } + ] + } +} +``` + +## Step 3: Core Agent Logic (Gist) + +The agent generates recipes based on multiple inputs: + +```python +# Simplified agent structure +def recipe_create( + ingredients: str, + dietary_restrictions: str = "", + time_limit: str = "" +) -> Dict[str, Any]: + """ + Generates a complete recipe: + 1. Analyzes available ingredients + 2. Considers dietary restrictions + 3. Respects time constraints + 4. Generates recipe name, ingredients list, and instructions + 5. Returns structured recipe data + """ + # Process inputs + ingredient_list = parse_ingredients(ingredients) + restrictions = parse_restrictions(dietary_restrictions) + time_constraint = parse_time_limit(time_limit) + + # Generate recipe + recipe = generate_recipe( + ingredients=ingredient_list, + restrictions=restrictions, + time_limit=time_constraint + ) + + return { + "name": recipe["name"], + "ingredients": recipe["ingredients"], + "instructions": recipe["instructions"], + "prep_time": recipe["prep_time"], + "cook_time": recipe["cook_time"], + "servings": recipe["servings"], + "dietary_info": recipe["dietary_info"] + } + +def recipe_stream( + ingredients: str, + dietary_restrictions: str = "", + time_limit: str = "" +) -> Iterator[str]: + """ + Streams recipe generation in real-time: + 1. Streams recipe name + 2. Streams ingredients list + 3. Streams instructions step by step + 4. Provides real-time feedback + """ + yield "🍳 Creating your personalized recipe...\n\n" + + # Stream recipe name + recipe_name = generate_recipe_name(ingredients, dietary_restrictions) + yield f"**Recipe:** {recipe_name}\n\n" + + # Stream ingredients + yield "**Ingredients:**\n" + for ingredient in get_ingredients(ingredients, dietary_restrictions): + yield f"- {ingredient}\n" + yield "\n" + + # Stream instructions + yield "**Instructions:**\n" + for i, step in enumerate(get_instructions(ingredients, time_limit), 1): + yield f"{i}. {step}\n" + + yield "\n✨ Enjoy your meal!" +``` + +## Step 4: Backend Integration + +The Flask backend provides REST API endpoints: + +```python +# Backend API structure +@app.route('/api/recipe', methods=['POST']) +def create_recipe(): + """ + Synchronous recipe creation endpoint + """ + client = RunAgentClient( + agent_id=agent_id, + entrypoint_tag="recipe_create", + local=False + ) + + result = client.run( + ingredients=ingredients, + dietary_restrictions=dietary_restrictions, + time_limit=time_limit + ) + + return jsonify(result) + +@app.route('/api/recipe/stream', methods=['POST']) +def create_recipe_stream(): + """ + Streaming recipe creation endpoint + """ + client = RunAgentClient( + agent_id=agent_id, + entrypoint_tag="recipe_stream", + local=False + ) + + def generate(): + for chunk in client.run( + ingredients=ingredients, + dietary_restrictions=dietary_restrictions, + time_limit=time_limit + ): + yield f"data: {json.dumps(chunk)}\n\n" + + return Response(generate(), mimetype='text/event-stream') +``` + +## Step 5: Frontend Integration + +The React frontend provides a user-friendly interface: + +**Key Features:** +- Ingredient input (text or list) +- Dietary restrictions selector +- Time limit input +- Recipe display with formatting +- Streaming recipe generation +- Example recipe suggestions +- Recipe history (optional) + +## Step 6: Deployment + +### Local Deployment + +```bash +# 1. Deploy the RunAgent agent +cd examples/recipe_creator/agents +runagent serve . + +# 2. Start the backend +cd ../backend +python app.py + +# 3. Start the frontend +cd ../frontend +npm run dev +``` + +### Production Deployment + +The agent can be deployed to RunAgent Cloud: + +```bash +runagent deploy . +``` + +## What You've Accomplished + +You've built a complete recipe creation system: + + + + Creates personalized recipes from available ingredients + + + Streams recipe generation for better user experience + + + Handles dietary restrictions and preferences + + + Considers time constraints for meal preparation + + + +## Key Features + +### Ingredient-Based Generation +- Analyzes available ingredients +- Suggests complementary ingredients +- Creates recipes that maximize ingredient usage +- Provides ingredient substitutions when needed + +### Dietary Restriction Handling +- Supports vegetarian, vegan, gluten-free, etc. +- Accommodates allergies and intolerances +- Suggests alternative ingredients +- Maintains recipe quality with restrictions + +### Time-Aware Recipes +- Respects time constraints +- Suggests quick recipes for busy schedules +- Provides prep and cook time estimates +- Offers time-saving tips + +### Streaming Support +- Real-time recipe generation +- Progressive display of information +- Better user experience +- Immediate feedback + +## Example Usage + +```python +from runagent import RunAgentClient + +# Synchronous recipe creation +client = RunAgentClient( + agent_id="your_agent_id", + entrypoint_tag="recipe_create", + local=False +) + +recipe = client.run( + ingredients="chicken breast, broccoli, rice, garlic", + dietary_restrictions="", + time_limit="30 minutes" +) + +# Streaming recipe creation +stream_client = RunAgentClient( + agent_id="your_agent_id", + entrypoint_tag="recipe_stream", + local=False +) + +for chunk in stream_client.run( + ingredients="pasta, mushrooms, spinach, cream", + dietary_restrictions="vegetarian", + time_limit="25 minutes" +): + print(chunk, end="", flush=True) +``` + +## Example Recipes + +The agent can generate various types of recipes: + +**Quick Meals:** +- 15-minute pasta dishes +- One-pan meals +- Quick stir-fries + +**Dietary-Specific:** +- Vegan alternatives +- Gluten-free options +- Low-carb meals + +**Ingredient-Focused:** +- Recipes using specific ingredients +- Leftover transformations +- Seasonal ingredient recipes + +## Next Steps + + + + Add features like nutritional info and meal planning + + + Improve recipe quality with better prompts + + + Deploy to production with proper scaling + + + Explore the complete example code + + + +## Repository + +View the complete example code and documentation: + +**Repository**: [https://github.com/runagent-dev/runagent/tree/main/examples/recipe_creator](https://github.com/runagent-dev/runagent/tree/main/examples/recipe_creator) + +The repository includes: +- Complete agent implementation +- Flask backend API with streaming support +- React frontend application +- Example recipe queries +- Configuration files + + +**πŸŽ‰ Great job!** You've learned how to build a practical recipe creation system using RunAgent. This demonstrates how AI agents can solve everyday problems with personalized solutions! + + + diff --git a/examples/lead-agent/README.md b/examples/lead-agent/README.md new file mode 100644 index 0000000..18504de --- /dev/null +++ b/examples/lead-agent/README.md @@ -0,0 +1,265 @@ +# Lead Score SaaS + +AI-powered lead scoring SaaS solution using RunAgent and CrewAI. The RunAgent agent uses CrewAI to analyze candidates, score them against job descriptions, and generate personalized follow-up emails. + +## Prerequisites + +- Python 3.10 or higher +- Node.js 18 or higher +- npm or yarn +- OpenAI API key +- Serper API key (for web search) + +## What the Agent Does + +The RunAgent agent provides two main entry points: + +1. **`lead_score_flow`**: Complete workflow that: + - Scores all candidates against a job description using AI analysis + - Ranks candidates by their match score + - Generates personalized follow-up emails for all candidates + - Returns top N candidates with detailed scoring rationale + +2. **`score_candidate`**: Score a single candidate: + - Analyzes candidate bio, skills, and experience + - Compares against job requirements + - Returns score (0-100) with detailed reasoning + +The agent uses CrewAI with specialized crews: +- **LeadScoreCrew**: Analyzes and scores candidates based on job fit +- **LeadResponseCrew**: Generates personalized email responses + +## Architecture + +``` +React Frontend (Port 5173) + ↓ HTTP REST API +Flask Backend (Port 8000) + ↓ RunAgent Python SDK +RunAgent Agent (CrewAI Flow) + β”œβ”€β”€ LeadScoreCrew (scoring) + └── LeadResponseCrew (email generation) +``` + +## Quick Start + +### 1. Initialize and Configure RunAgent Agent + +```bash +cd lead-score-flow + +# Initialize the agent (creates runagent.config.json) +runagent init . --framework crewai + +# This generates a unique agent_id and creates runagent.config.json +``` + +The `runagent init` command creates `runagent.config.json` with: +- Generated `agent_id` (unique identifier) +- Framework configuration (crewai) +- Empty `entrypoints` array + +**Configure Entrypoints:** + +The agent already has entrypoints configured in `runagent.config.json`: +```json +{ + "agent_architecture": { + "entrypoints": [ + { + "file": "main.py", + "module": "run_flow", + "tag": "lead_score_flow" + }, + { + "file": "main.py", + "module": "score_single_candidate", + "tag": "score_candidate" + } + ] + } +} +``` + +**Important:** If you manually edit the `agent_id` in `runagent.config.json`, you must register it: +```bash +runagent register . +``` + +### 2. Setup Environment and Dependencies + +```bash +# Create .env file +cat > .env << EOF +OPENAI_API_KEY=your_openai_key_here +SERPER_API_KEY=your_serper_key_here +EOF + +# Install dependencies +pip install runagent +crewai install +``` + +### 3. Deploy RunAgent Agent Locally + +```bash +# Start the RunAgent server +runagent serve . + +# Copy the Agent ID from the output +``` + +### 4. Deploy Backend API + +```bash +cd ../backend + +# Create virtual environment +python -m venv venv +source venv/bin/activate # On Windows: venv\Scripts\activate + +# Install dependencies +pip install -r requirements.txt + +# Start server +python app.py +``` + +### 5. Deploy Frontend + +```bash +cd ../frontend + +# Install dependencies +npm install + +# Start development server +npm run dev +``` + +The application will be available at `http://localhost:5173`. + +## Usage + +1. **Configure Settings** + - Enter your RunAgent Agent ID + - Paste the job description + - Set the number of top candidates (default: 3) + +2. **Upload Candidates** + - Prepare a CSV file with columns: `id,name,email,bio,skills` + - Upload via the interface + +3. **View Results** + - See scored candidates ranked by AI + - Download scores as CSV + - Download personalized emails + +### Sample CSV Format + +```csv +id,name,email,bio,skills +1,John Doe,john@example.com,"Experienced React developer with 5 years","React, Node.js, TypeScript" +2,Jane Smith,jane@example.com,"Full-stack developer specializing in AI","Python, React, TensorFlow" +``` + +## Production Deployment with RunAgent Cloud + +For production, deploy the agent to RunAgent Cloud for better scalability and reliability. + +### Prerequisites + +1. **RunAgent Account** - Sign up at [run-agent.ai](https://run-agent.ai) +2. **API Key** - Get your API key from the dashboard +3. **Authenticate CLI** - Configure your CLI with your API key + +### Authentication Setup + +```bash +# Setup authentication +runagent setup --api-key + +# Verify configuration +runagent setup --api-key +``` + +### Deploy to Cloud + +```bash +cd lead-score-flow + +# Deploy to RunAgent Cloud (combines upload + start) +runagent deploy . + +# You'll receive output like: +# βœ… Full deployment successful! +# πŸ†” Agent ID: abc-123-def-456 +# 🌐 Endpoint: https://api.run-agent.ai/api/v1/agents/abc-123-def-456 +``` + +**Alternative: Two-Step Deploy** + +For more control, upload and start separately: + +```bash +# Step 1: Upload agent +runagent upload . + +# Step 2: Start agent +runagent start --id +``` + +**Benefits of RunAgent Cloud:** +- Managed infrastructure with automatic scaling +- No need to run `runagent serve` locally +- Better performance and reliability +- Access from anywhere without local setup +- 24/7 uptime +- Full monitoring dashboard + +After deployment, update your backend to use the cloud agent ID instead of the local one. The backend will connect to the cloud agent automatically when using `local=False` in the RunAgent client configuration. + +## Security + +- Never commit `.env` files +- Use environment variables for API keys +- Configure proper CORS origins in production +- Implement rate limiting and authentication + +## Troubleshooting + +### Agent Not Found +```bash +runagent serve . +runagent list +``` + +### Connection Refused +```bash +curl http://localhost:8000/api/health +``` + +### CSV Upload Error +- Ensure CSV has required columns: id, name, email, bio, skills +- Check CSV encoding (should be UTF-8) + +## Customization + +- **Scoring Criteria**: Edit `lead-score-flow/src/lead_score_flow/constants.py` +- **Email Templates**: Update `lead_response_crew` configuration +- **Additional Data**: Add columns to CSV and update models + +## Support + +- Documentation: https://docs.run-agent.ai +- Discord: https://discord.gg/Q9P9AdHVHz +- GitHub Issues: https://github.com/runagent-dev/runagent + +## License + +MIT License + +--- + +For detailed deployment instructions, see [deployment_guide.md](./deployment_guide.md). + diff --git a/examples/lead-agent/backend-rust/src/main.rs b/examples/lead-agent/backend-rust/src/main.rs index ece94ff..e68810a 100644 --- a/examples/lead-agent/backend-rust/src/main.rs +++ b/examples/lead-agent/backend-rust/src/main.rs @@ -10,7 +10,7 @@ use serde_json::{json, Value}; use tower_http::cors::{CorsLayer, AllowOrigin}; // RunAgent configuration -const RUNAGENT_ID: &str = "93eaf000-0000-0000-0000-000000000000"; +const RUNAGENT_ID: &str = "bd87871d-b4c4-4ec1-990b-bef0ea4766f7"; // Request/Response types #[derive(Deserialize)] @@ -150,22 +150,26 @@ async fn score_leads( println!("[DEBUG] Agent result type: {}", result); println!("[DEBUG] Agent result keys: {:?}", result.as_object().map(|o| o.keys().collect::>())); - // Check if result is a JSON string that needs parsing - let final_result = if let Some(result_str) = result.as_str() { - match serde_json::from_str::(result_str) { - Ok(parsed) => { - println!("[DEBUG] Parsed JSON string result"); - parsed + // Extract payload field if it exists (RunAgent wraps result in {"payload": "...", "type": "object"}) + let final_result = if let Some(obj) = result.as_object() { + if let Some(payload_value) = obj.get("payload") { + if let Some(payload_str) = payload_value.as_str() { + // Try to parse the payload JSON string + serde_json::from_str::(payload_str).unwrap_or(result) + } else { + result } - Err(e) => { - println!("[DEBUG] Failed to parse JSON string: {}", e); - println!("[DEBUG] Result string length: {}", result_str.len()); - println!("[DEBUG] Result string preview (first 500 chars): {}", - result_str.chars().take(500).collect::()); - // If parsing fails, return the raw string as a JSON value + } else { + // Check if result is a JSON string that needs parsing + if let Some(result_str) = result.as_str() { + serde_json::from_str::(result_str).unwrap_or(result) + } else { result } } + } else if let Some(result_str) = result.as_str() { + // Result is a string, try to parse it + serde_json::from_str::(result_str).unwrap_or(result) } else { result }; diff --git a/examples/lead-agent/lead-score-flow/runagent.config.json b/examples/lead-agent/lead-score-flow/runagent.config.json index 8c6ba6b..d430a5b 100644 --- a/examples/lead-agent/lead-score-flow/runagent.config.json +++ b/examples/lead-agent/lead-score-flow/runagent.config.json @@ -1,28 +1,32 @@ { - "agent_name": "Lead Score Flow", - "description": "AI-powered lead scoring and response system using CrewAI", - "framework": "crewai", - "template": "lead_score", - "version": "1.0.0", - "created_at": "2025-10-26", - "template_source": { - "repo_url": "https://github.com/runagent-dev/runagent.git", - "path": "flows/lead-score-flow", - "author": "runagent" - }, - "agent_architecture": { - "entrypoints": [ - { - "file": "main.py", - "module": "run_flow", - "tag": "lead_score_flow" - }, - { - "file": "main.py", - "module": "score_single_candidate", - "tag": "score_candidate" - } - ] - }, - "agent_id": "89aef000-0000-0000-0000-000000000000" - } \ No newline at end of file + "agent_name": "HR Talent Hunt", + "description": "Candidate lead generation for HR", + "framework": "crewai", + "template": "", + "version": "1.0.0", + "created_at": "2025-11-13T10:15:37.208223", + "template_source": { + "repo_url": "https://github.com/runagent-dev/runagent.git", + "author": "runagent-cli", + "path": "/home/azureuser/runagent/examples/lead-agent/lead-score-flow" + }, + "agent_architecture": { + "entrypoints": [ + { + "file": "main.py", + "module": "run_flow", + "tag": "lead_score_flow" + }, + { + "file": "main.py", + "module": "score_single_candidate", + "tag": "score_candidate" + } + ] + }, + "env_vars": {}, + "agent_id": "bd87871d-b4c4-4ec1-990b-bef0ea4766f7", + "auth_settings": { + "type": "api_key" + } +} \ No newline at end of file diff --git a/examples/lead-agent/runagent_sdk/rust/src/main.rs b/examples/lead-agent/runagent_sdk/rust/src/main.rs index 8112e5c..1897313 100644 --- a/examples/lead-agent/runagent_sdk/rust/src/main.rs +++ b/examples/lead-agent/runagent_sdk/rust/src/main.rs @@ -6,7 +6,7 @@ async fn main() -> Result<(), Box> { println!("πŸ§ͺ Testing Lead Score Agent with Rust SDK"); // Replace with your actual agent ID from `runagent serve` - let agent_id = "dd520db6-5ff6-4b2b-9eea-e3c50453b4d9"; + let agent_id = "bd87871d-b4c4-4ec1-990b-bef0ea4766f7"; println!("\nπŸš€ Testing Lead Score Flow"); println!("============================"); @@ -15,7 +15,7 @@ async fn main() -> Result<(), Box> { let client = RunAgentClient::new( agent_id, "lead_score_flow", // entrypoint_tag - true, // local = true + false, // local = true ).await?; // Call the lead score flow with parameters diff --git a/examples/recipe_creator/agents/runagent.config.json b/examples/recipe_creator/agents/runagent.config.json index 01e1e52..017a78a 100644 --- a/examples/recipe_creator/agents/runagent.config.json +++ b/examples/recipe_creator/agents/runagent.config.json @@ -1,28 +1,33 @@ { - "agent_name": "Recipe Creator Agent", - "description": "AI-powered recipe creation assistant", - "framework": "agno", - "template": "custom", - "version": "1.0.0", - "created_at": "2025-10-27 00:00:00", - "template_source": { - "repo_url": "https://github.com/runagent-dev/runagent.git", - "path": "templates/agno/custom", - "author": "custom" - }, - "agent_architecture": { - "entrypoints": [ - { - "file": "recipe_agent.py", - "module": "create_recipe", - "tag": "recipe_create" - }, - { - "file": "recipe_agent.py", - "module": "create_recipe_stream", - "tag": "recipe_stream" - } - ] - }, - "agent_id": "76aef000-0000-0000-0000-000000000000" - } \ No newline at end of file + "agent_name": "Instant Recipe Suggestion", + "description": "With existing ingredients in my fridge, it will suggest the best recipe for me", + "framework": "default", + "template": "", + "version": "1.0.0", + "created_at": "2025-11-13T06:21:19.646412", + "template_source": { + "repo_url": "https://github.com/runagent-dev/runagent.git", + "author": "runagent-cli", + "path": "/home/azureuser/runagent/examples/recipe_creator/agents" + }, + "agent_architecture": { + "entrypoints": [ + { + "file": "recipe_agent.py", + "module": "create_recipe", + "tag": "recipe_create" + }, + { + "file": "recipe_agent.py", + "module": "create_recipe_stream", + "tag": "recipe_stream" + } + + ] + }, + "env_vars": {}, + "agent_id": "9cd7f85d-248c-4931-831a-5b4d43a01a78", + "auth_settings": { + "type": "api_key" + } +} \ No newline at end of file diff --git a/examples/recipe_creator/backend/app.py b/examples/recipe_creator/backend/app.py index 9a8b600..73188d3 100644 --- a/examples/recipe_creator/backend/app.py +++ b/examples/recipe_creator/backend/app.py @@ -9,13 +9,13 @@ # Initialize RunAgent client recipe_client = RunAgentClient( - agent_id="6f15f51e-0b6e-479a-ae8c-8174db2712fd", + agent_id="7cd7f85d-248c-4931-831a-5b4d43a01a78", entrypoint_tag="recipe_create", local=False ) stream_client = RunAgentClient( - agent_id="6f15f51e-0b6e-479a-ae8c-8174db2712fd", + agent_id="7cd7f85d-248c-4931-831a-5b4d43a01a78", entrypoint_tag="recipe_stream", local=False ) diff --git a/examples/recipe_creator/sdk/python/test.py b/examples/recipe_creator/sdk/python/test.py index f305d5e..14330b8 100644 --- a/examples/recipe_creator/sdk/python/test.py +++ b/examples/recipe_creator/sdk/python/test.py @@ -21,7 +21,7 @@ def test_non_streaming(): print("-" * 50) client = RunAgentClient( - agent_id="76aef000-0000-0000-0000-000000000000", + agent_id="9cd7f85d-248c-4931-831a-5b4d43a01a78", entrypoint_tag="recipe_create", local=False ) @@ -47,7 +47,7 @@ def test_streaming(): print("-" * 50) client = RunAgentClient( - agent_id="76aef000-0000-0000-0000-000000000000", + agent_id="9cd7f85d-248c-4931-831a-5b4d43a01a78", entrypoint_tag="recipe_stream", local=False ) diff --git a/runagent-rust/Cargo.toml b/runagent-rust/Cargo.toml index 733ae1b..d426fa0 100644 --- a/runagent-rust/Cargo.toml +++ b/runagent-rust/Cargo.toml @@ -6,15 +6,16 @@ resolver = "2" [workspace.dependencies] # Async runtime tokio = { version = "1.35", features = ["full"] } -tokio-tungstenite = "0.21" +tokio-tungstenite = { version = "0.21", features = ["rustls-tls-native-roots"] } # HTTP and web -reqwest = { version = "0.11", features = ["json", "stream"] } +reqwest = { version = "0.11", features = ["json", "stream", "rustls-tls"] } axum = { version = "0.7.6", features = ["ws"] } tower = "0.4" tower-http = { version = "0.5", features = ["cors", "fs"] } hyper = { version = "1.0", features = ["full"] } + # Serialization serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/runagent-rust/runagent/Cargo.toml b/runagent-rust/runagent/Cargo.toml index 1a75289..8a731fd 100644 --- a/runagent-rust/runagent/Cargo.toml +++ b/runagent-rust/runagent/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "runagent" -version = "0.1.32" +version = "0.1.33" edition = "2021" description = "RunAgent SDK for Rust - Client SDK for interacting with deployed AI agents" license = "MIT" diff --git a/runagent-rust/runagent/README.md b/runagent-rust/runagent/README.md index d892cec..5366304 100644 --- a/runagent-rust/runagent/README.md +++ b/runagent-rust/runagent/README.md @@ -7,29 +7,29 @@ --- -## 🎯 What is RunAgent? +## What is RunAgent? RunAgent is a comprehensive Rust SDK for deploying and managing AI agents with support for multiple frameworks including **LangChain**, **LangGraph**, **LlamaIndex**, and more. Whether you're building chatbots, autonomous agents, or complex AI workflows, RunAgent provides the tools you need to deploy, test, and scale your AI applications. --- -## ✨ Features +## Features -- πŸ€– **Multi-Framework Support**: LangChain, LangGraph, LlamaIndex, Letta, CrewAI, AutoGen -- πŸš€ **Local & Remote Deployment**: Deploy agents locally or to remote servers -- ⚑ **Real-time Streaming**: WebSocket-based streaming for real-time interactions -- πŸ’Ύ **Database Management**: SQLite-based agent metadata and history -- πŸ“‹ **Template System**: Pre-built templates for rapid setup -- πŸ›‘οΈ **Type Safety**: Full Rust type safety with error handling -- πŸ”„ **Async/Await**: Powered by Tokio for async ops +- **Multi-Framework Support**: LangChain, LangGraph, LlamaIndex, Letta, CrewAI, AutoGen +- **Local & Remote Deployment**: Deploy agents locally or to remote servers +- **Real-time Streaming**: WebSocket-based streaming for real-time interactions +- **Database Management**: SQLite-based agent metadata and history +- **Template System**: Pre-built templates for rapid setup +- **Type Safety**: Full Rust type safety with error handling +- **Async/Await**: Powered by Tokio for async operations --- -## πŸ“¦ Installation +## Installation ```bash cargo add runagent tokio -```` +``` Or add manually to `Cargo.toml`: @@ -37,156 +37,242 @@ Or add manually to `Cargo.toml`: [dependencies] runagent = "0.1.0" tokio = { version = "1.35", features = ["full"] } +serde_json = "1.0" +futures = "0.3" ``` --- -## πŸƒ Quick Start +## Quick Start + +> **RunAgent Cloud** is the recommended way to get started. Deploy and interact with agents hosted on RunAgent's infrastructure without managing your own servers. + +### RunAgent Cloud + +RunAgent Cloud allows you to deploy and interact with agents hosted on RunAgent's infrastructure. This is the recommended way to get started quickly. + +**Key Benefits:** +- No server setup required +- Automatic scaling +- Managed infrastructure +- Simple authentication via API key + +#### Step 1: Set Up Authentication + +**Important:** You must export your API key before running your application: -### βœ… Basic Agent Interaction +```bash +export RUNAGENT_API_KEY="your-api-key" +``` + +You can get your API key from the [RunAgent Dashboard](https://runagent.dev). + +#### Step 2: Connect to Your Agent + +When connecting to RunAgent Cloud, set `local = false`: ```rust -use runagent::prelude::*; +use runagent::client::RunAgentClient; + +let client = RunAgentClient::new( + "your-agent-id", // Your agent ID from RunAgent Cloud + "agno_print_response", // Entrypoint tag + false // local = false for cloud +).await?; +``` + +#### Step 3: Run Your Agent + +**Non-Streaming Example:** + +```rust +use runagent::client::RunAgentClient; use serde_json::json; #[tokio::main] async fn main() -> Result<(), Box> { - runagent::init_logging(); - let client = RunAgentClient::new("my-agent-id", "generic", true).await?; - - let response = client.run(&[ - ("message", json!("Hello, world!")), - ("temperature", json!(0.7)) - ]).await?; - + // Set RUNAGENT_API_KEY environment variable before running + let agent_id = "your-agent-id"; + + // Connect to cloud agent (local = false) + let client = RunAgentClient::new(agent_id, "agno_print_response", false).await?; + + // Run with positional and keyword arguments + let response = client.run_with_args( + &[json!("Write small paragraph on how i met your mother tv series")], // positional args + &[] // no keyword args + ).await?; + println!("Response: {}", response); Ok(()) } ``` -### πŸ” Streaming Agent Interaction +**Streaming Example:** ```rust -use runagent::prelude::*; -use futures::StreamExt; +use runagent::client::RunAgentClient; use serde_json::json; +use futures::StreamExt; #[tokio::main] async fn main() -> Result<(), Box> { - let client = RunAgentClient::new("my-agent-id", "generic_stream", true).await?; - + // Set RUNAGENT_API_KEY environment variable before running + let agent_id = "your-agent-id"; + + // Connect to cloud agent with streaming entrypoint + let client = RunAgentClient::new(agent_id, "agno_print_response_stream", false).await?; + + // Run with streaming let mut stream = client.run_stream(&[ - ("message", json!("Tell me a story")) + ("prompt", json!("is investing in AI is good idea?")) ]).await?; - - while let Some(chunk) = stream.next().await { - match chunk { - Ok(data) => println!("Chunk: {}", data), - Err(e) => eprintln!("Stream error: {}", e), + + while let Some(chunk_result) = stream.next().await { + match chunk_result { + Ok(chunk) => println!("{}", chunk), + Err(e) => { + println!("Error: {}", e); + break; + } } } - + Ok(()) } ``` ---- - -## πŸ”§ Configuration - -### βœ… Environment Variables +**Complete Workflow:** ```bash -# API Configuration +# 1. Export your API key export RUNAGENT_API_KEY="your-api-key" -export RUNAGENT_BASE_URL="https://api.runagent.ai" - -# Local Configuration -export RUNAGENT_CACHE_DIR="~/.runagent" -export RUNAGENT_LOGGING_LEVEL="info" -``` - -### βœ… Configuration Builder - -```rust -use runagent::RunAgentConfig; -let config = RunAgentConfig::new() - .with_api_key("your-api-key") - .with_base_url("https://api.runagent.ai") - .with_logging() - .build(); +# 2. Run your application +cargo run ``` --- -## 🎯 Framework-Specific Examples +### Local Development + +For local development, you can run agents on your own machine. Set `local = true` when creating the client. -### LangChain Integration +#### Basic Agent Interaction (Local) ```rust -use runagent::prelude::*; +use runagent::client::RunAgentClient; use serde_json::json; #[tokio::main] async fn main() -> Result<(), Box> { - let client = RunAgentClient::new("langchain-agent", "invoke", true).await?; - - let response = client.run(&[ - ("input", json!({ - "messages": [ - {"role": "user", "content": "What is the weather like?"} - ] - })) - ]).await?; - - println!("LangChain response: {}", response); + let agent_id = "your-agent-id"; + + // Connect to local agent (local = true) + let client = RunAgentClient::new(agent_id, "lead_score_flow", true).await?; + + // Run with keyword arguments only + let response = client.run_with_args( + &[], // no positional args + &[ + ("top_n", json!(1)), + ("generate_emails", json!(true)) + ] + ).await?; + + println!("Response: {}", serde_json::to_string_pretty(&response)?); Ok(()) } ``` -### LangGraph Workflows +### Connecting to Local Agent with Explicit Address ```rust -use runagent::prelude::*; +use runagent::client::RunAgentClient; use serde_json::json; -use futures::StreamExt; #[tokio::main] async fn main() -> Result<(), Box> { - let client = RunAgentClient::new("langgraph-agent", "stream", true).await?; - - let mut stream = client.run_stream(&[ - ("input", json!({ - "messages": [{"role": "user", "content": "Analyze this data"}] - })) + let agent_id = "your-agent-id"; + + // Connect to local agent with explicit host and port + let client = RunAgentClient::with_address( + agent_id, + "generic", + true, + Some("127.0.0.1"), + Some(8452) + ).await?; + + let response = client.run(&[ + ("message", json!("Hello, world!")) ]).await?; - - while let Some(chunk) = stream.next().await { - match chunk { - Ok(data) => { - if let Some(node) = data.get("node") { - println!("Executing node: {}", node); - } - } - Err(e) => eprintln!("Error: {}", e), - } - } - + + println!("Response: {}", response); Ok(()) } ``` --- -## πŸ—οΈ Architecture +## Configuration + +### RunAgent Cloud Setup + +**Required:** Set your API key as an environment variable before running your application: + +```bash +export RUNAGENT_API_KEY="your-api-key" +``` + +**Optional:** Customize the base URL (defaults to `https://api.runagent.ai`): + +```bash +export RUNAGENT_BASE_URL="https://api.runagent.ai" +``` + +### Local Development Setup + +For local development, you can configure cache and logging: + +```bash +export RUNAGENT_CACHE_DIR="~/.runagent" +export RUNAGENT_LOGGING_LEVEL="info" +``` + +### Quick Reference + +| Setting | RunAgent Cloud | Local Development | +|---------|---------------|-------------------| +| **API Key** | **Required** (`RUNAGENT_API_KEY`) | Not needed | +| **Base URL** | Optional (defaults to `https://api.runagent.ai`) | Not needed | +| **Client Parameter** | `local = false` | `local = true` | +| **Agent Location** | RunAgent infrastructure | Your local machine | + +### Configuration Builder + +You can also configure the SDK programmatically: + +```rust +use runagent::RunAgentConfig; + +let config = RunAgentConfig::new() + .with_api_key("your-api-key") + .with_base_url("https://api.runagent.ai") + .with_logging() + .build(); +``` + +--- + +## Architecture ### Core Components * **Client**: High-level client for agent interaction -* **Server**: FastAPI-like local server for testing -* **Database**: SQLite-based agent history store -* **Framework Executors**: Executors for LangChain, LangGraph, etc. +* **REST Client**: HTTP-based client for non-streaming requests +* **Socket Client**: WebSocket-based client for streaming interactions +* **Database**: SQLite-based agent history store (optional) * **Serialization**: Safe messaging via WebSocket ### Optional Features @@ -195,42 +281,58 @@ Enable or disable features in `Cargo.toml`: ```toml [dependencies] -runagent = { version = "0.1.0", features = ["db", "server"] } +runagent = { version = "0.1.0", features = ["db"] } ``` -Available: +Available features: -* `db` (default): Enable database support -* `server` (default): Enable local server +* `db` (default): Enable database support for local agent management --- -## πŸ“š API Reference +## API Reference ### `RunAgentClient` -* `new(agent_id, entrypoint_tag, local)` -* `run(input_kwargs)` -* `run_stream(input_kwargs)` -* `health_check()` +Main client for interacting with RunAgent deployments. + +#### Methods + +* `new(agent_id, entrypoint_tag, local)` - Create a new client + * `agent_id`: The agent identifier + * `entrypoint_tag`: The entrypoint function tag (e.g., "agno_print_response") + * `local`: `true` for local agents, `false` for cloud agents + +* `with_address(agent_id, entrypoint_tag, local, host, port)` - Create client with explicit address -### `LocalServer` +* `run(input_kwargs)` - Run agent with keyword arguments only + * Returns: `RunAgentResult` -* `new(agent_id, agent_path, host, port)` -* `from_path(agent_path, host, port)` -* `start()` -* `get_info()` +* `run_with_args(input_args, input_kwargs)` - Run agent with both positional and keyword arguments + * `input_args`: Slice of positional arguments as `Value` + * `input_kwargs`: Slice of tuples `(&str, Value)` for keyword arguments + +* `run_stream(input_kwargs)` - Run agent with streaming response + * Returns: `RunAgentResult> + Send>>>` + +* `run_stream_with_args(input_args, input_kwargs)` - Run agent with streaming and both argument types + +* `health_check()` - Check if the agent is available + +* `get_agent_architecture()` - Get the agent's architecture information ### `DatabaseService` -* `new(db_path)` -* `add_agent(agent)` -* `list_agents()` -* `get_capacity_info()` +Database service for managing local agent metadata (requires `db` feature). + +* `new(db_path)` - Create a new database service +* `add_agent(agent)` - Add an agent to the database +* `list_agents()` - List all agents in the database +* `get_agent(agent_id)` - Get agent information by ID --- -## πŸ” Error Handling +## Error Handling ```rust use runagent::{RunAgentError, RunAgentResult}; @@ -244,11 +346,7 @@ fn handle_errors() -> RunAgentResult<()> { } Err(RunAgentError::Connection { message }) => { eprintln!("Connection error: {}", message); - if err.is_retryable() { - retry_operation() - } else { - Err(err) - } + Err(RunAgentError::connection("Connection failed")) } Err(e) => Err(e), } @@ -257,7 +355,7 @@ fn handle_errors() -> RunAgentResult<()> { --- -## πŸ§ͺ Testing +## Testing ```bash cargo test @@ -267,19 +365,18 @@ cargo test --test integration --- -## πŸ“– Examples +## Examples -See `examples/` folder for: +See the `examples/` folder for complete examples: -* βœ… Basic usage -* πŸ” Streaming -* πŸ’Ύ Database -* 🌐 Server setup -* 🎯 Framework integrations +* Basic usage with cloud agents +* Streaming interactions +* Local agent connections +* Framework integrations --- -## 🀝 Contributing +## Contributing We welcome contributions! See `CONTRIBUTING.md` for guidelines. @@ -294,34 +391,34 @@ cargo test --- -## πŸ“‹ Roadmap +## Roadmap * Python interop via PyO3 * Additional framework support -* Enhanced streaming +* Enhanced streaming capabilities * Production deployment tools * Monitoring & observability * CLI tool integration --- -## πŸ”— Links +## Links -* 🌍 [Website](https://runagent.dev) -* πŸ“š [Documentation](https://docs.runagent.dev) -* πŸ’» [Repository](https://github.com/runagent-dev/runagent) -* ❓ [Issues](https://github.com/runagent-dev/runagent/issues) -* 🐍 [Python SDK](https://pypi.org/project/runagent/) +* [Website](https://run-agent.ai/) +* [Documentation](https://docs.run-agent.ai/explanation/introduction) +* [Repository](https://github.com/runagent-dev/runagent) +* [Issues](https://github.com/runagent-dev/runagent/issues) +* [Python SDK](https://pypi.org/project/runagent/) --- -## πŸ“„ License +## License This project is licensed under the MIT License - see the [LICENSE](./LICENSE) file. --- -## πŸ™ Acknowledgments +## Acknowledgments * Built with [Tokio](https://tokio.rs) * Uses [Axum](https://github.com/tokio-rs/axum) diff --git a/runagent-rust/runagent/src/client/socket_client.rs b/runagent-rust/runagent/src/client/socket_client.rs index 86bc476..2ca94f0 100644 --- a/runagent-rust/runagent/src/client/socket_client.rs +++ b/runagent-rust/runagent/src/client/socket_client.rs @@ -205,7 +205,8 @@ mod tests { fn test_websocket_url_construction() { let client = SocketClient::new("ws://localhost:8000", None, Some("/api/v1")).unwrap(); let url = client.get_websocket_url("test-agent", "generic").unwrap(); - assert_eq!(url.as_str(), "ws://localhost:8000/api/v1/agents/test-agent/execute/generic"); + // Updated expected URL to match the actual implementation + assert_eq!(url.as_str(), "ws://localhost:8000/api/v1/agents/test-agent/run-stream"); } #[test] diff --git a/templates/agno/default/runagent.config.json b/templates/agno/default/runagent.config.json index 4752759..f132a99 100644 --- a/templates/agno/default/runagent.config.json +++ b/templates/agno/default/runagent.config.json @@ -1,14 +1,14 @@ { - "agent_name": "A Rust backend agent for Agno", - "description": "A simple placeholder agent", + "agent_name": "Agno agent testing", + "description": "My AI agent", "framework": "agno", - "template": "default", + "template": "", "version": "1.0.0", - "created_at": "2025-06-25 13:42:03", + "created_at": "2025-11-14T16:17:22.317584", "template_source": { "repo_url": "https://github.com/runagent-dev/runagent.git", - "path": "templates/default", - "author": "sawradip" + "author": "runagent-cli", + "path": "/home/azureuser/runagent/templates/agno/default" }, "agent_architecture": { "entrypoints": [ @@ -24,6 +24,9 @@ } ] }, - "agent_id": "abc4f000-0000-0000-0000-000000000000" -} - + "env_vars": {}, + "agent_id": "ac29bd73-b3d3-42c8-a98f-5d7aec7ee919", + "auth_settings": { + "type": "api_key" + } +} \ No newline at end of file diff --git a/test_scripts/rust/test_agno/Cargo.toml b/test_scripts/rust/test_agno/Cargo.toml index 5cf216a..f6c5a2c 100644 --- a/test_scripts/rust/test_agno/Cargo.toml +++ b/test_scripts/rust/test_agno/Cargo.toml @@ -4,8 +4,8 @@ version = "0.1.1" edition = "2021" [dependencies] -# Assuming you're using the runagent Rust SDK -runagent = { path = "/home/azureuser/runagent/runagent-rust/runagent" } +# RunAgent Rust SDK from crates.io +runagent = "0.1.33" # Required dependencies tokio = { version = "1.0", features = ["full"] } diff --git a/test_scripts/rust/test_agno/src/main.rs b/test_scripts/rust/test_agno/src/main.rs index e43e920..7ee7882 100644 --- a/test_scripts/rust/test_agno/src/main.rs +++ b/test_scripts/rust/test_agno/src/main.rs @@ -1,68 +1,68 @@ -use runagent::client::RunAgentClient; -use serde_json::json; +// use runagent::client::RunAgentClient; +// use serde_json::json; -#[tokio::main] -async fn main() -> Result<(), Box> { - println!("πŸ§ͺ Testing agno Agent with Rust SDK"); +// #[tokio::main] +// async fn main() -> Result<(), Box> { +// println!("πŸ§ͺ Testing agno Agent with Rust SDK"); - let agent_id = "f9415c35-6c01-4f76-a9d5-ef2e11c08cbb"; +// let agent_id = "ac29ad73-b3d3-42c8-a98f-5d7aec7ee919"; - // Test: Non-streaming execution - println!("\nπŸš€ Testing Non-Streaming Execution"); - println!("=================================="); +// // Test: Non-streaming execution +// println!("\nπŸš€ Testing Non-Streaming Execution"); +// println!("=================================="); - // Connect directly with host and port since we know where the server is running - let client = RunAgentClient::new( - agent_id, - "agno_print_response", - false, // local = true - // Some("127.0.0.1"), - // Some(8452) // Use the port from your server output - ).await?; +// // Connect directly with host and port since we know where the server is running +// let client = RunAgentClient::new( +// agent_id, +// "agno_print_response", +// false, // local = true +// // Some("127.0.0.1"), +// // Some(8452) // Use the port from your server output +// ).await?; - // println!("πŸ”— Connected to agent at 127.0.0.1:8452"); +// // println!("πŸ”— Connected to agent at 127.0.0.1:8452"); - let response = client.run_with_args( - &[json!("Write small paragraph on how i met your mother tv series")], // positional args - &[] // no keyword args - ).await?; +// let response = client.run_with_args( +// &[json!("Write small paragraph on how i met your mother tv series")], // positional args +// &[] // no keyword args +// ).await?; - println!("βœ… Response received:"); - println!("{}",(&response)); +// println!("βœ… Response received:"); +// println!("{}",(&response)); - println!("\nβœ… Test completed successfully!"); +// println!("\nβœ… Test completed successfully!"); - Ok(()) -} +// Ok(()) +// } // ******************************Streaming Part with agno**************************************** -// use runagent::client::RunAgentClient; -// use serde_json::json; -// use futures::StreamExt; +use runagent::client::RunAgentClient; +use serde_json::json; +use futures::StreamExt; -// #[tokio::main] -// async fn main() -> Result<(), Box> { -// let agent_id = "f9415c35-6c01-4f76-a9d5-ef2e11c08cbb"; +#[tokio::main] +async fn main() -> Result<(), Box> { + let agent_id = "ac29ba73-b3d3-42c8-a98f-5d7aec7ee919"; -// println!("🌊 ag2 Streaming Test"); -// let client = RunAgentClient::new(agent_id, "agno_print_response_stream", false).await?; + println!("🌊 ag2 Streaming Test"); + let client = RunAgentClient::new(agent_id, "agno_print_response_stream", false).await?; -// let mut stream = client.run_stream(&[ -// ("prompt", json!("How many planets are there in the solar system?")) -// ]).await?; + let mut stream = client.run_stream(&[ + ("prompt", json!("is investing in AI is good idea?")) + ]).await?; -// while let Some(chunk_result) = stream.next().await { -// match chunk_result { -// Ok(chunk) => println!("{}", chunk), -// Err(e) => { -// println!("Error: {}", e); -// break; -// } -// } -// } + while let Some(chunk_result) = stream.next().await { + match chunk_result { + Ok(chunk) => println!("{}", chunk), + Err(e) => { + println!("Error: {}", e); + break; + } + } + } -// Ok(()) -// } \ No newline at end of file + Ok(()) +} \ No newline at end of file