-
Notifications
You must be signed in to change notification settings - Fork 4.7k
feat: add AgentOSClient class and cookbooks #5613
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
uzaxirr
wants to merge
13
commits into
main
Choose a base branch
from
os-client
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
dbaa606
feat: add AgentOSClient class and cookbooks.
uzaxirr 3af30f7
feat: add examples for running teams, workflows, evaluations, and con…
uzaxirr cd282c0
format
uzaxirr ed01a6b
fix: update event name and improve session handling in team and workf…
uzaxirr 0c7cdbe
format
uzaxirr 31b5fc2
Update cookbook/agent_os/client/02_run_agents.py
uzaxirr 7b95036
Update libs/agno/agno/os/client.py
uzaxirr f0e390d
Merge branch 'main' into os-client
uzaxirr 02eb135
Merge branch 'os-client' of https://github.com/agno-agi/agno into os-…
uzaxirr ddd1b3e
manu comments
uzaxirr 4e56faf
Merge branch 'main' into os-client
uzaxirr 779ed1b
Merge branch 'os-client' of https://github.com/agno-agi/agno into os-…
uzaxirr a1d5360
feat: Enhance AgentOS Client Documentation and Add Server Example
uzaxirr File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| """ | ||
| Basic AgentOSClient Example | ||
|
|
||
| This example demonstrates how to use AgentOSClient to connect to | ||
| a remote AgentOS instance and perform basic operations. | ||
|
|
||
| Prerequisites: | ||
| 1. Start an AgentOS server: | ||
| python -c " | ||
| from agno.agent import Agent | ||
| from agno.models.openai import OpenAIChat | ||
| from agno.os import AgentOS | ||
|
|
||
| agent = Agent( | ||
| name='Assistant', | ||
| model=OpenAIChat(id='gpt-4o-mini'), | ||
| instructions='You are a helpful assistant.', | ||
| ) | ||
| agent_os = AgentOS(agents=[agent]) | ||
| agent_os.serve() | ||
| " | ||
|
|
||
| 2. Run this script: python 01_basic_client.py | ||
| """ | ||
|
|
||
| import asyncio | ||
|
|
||
| from agno.os.client import AgentOSClient | ||
|
|
||
|
|
||
| async def main(): | ||
| # Connect to AgentOS using async context manager | ||
| async with AgentOSClient(base_url="http://localhost:7777") as client: | ||
| # Get AgentOS configuration | ||
| config = await client.get_config() | ||
| print(f"Connected to: {config.name or config.os_id}") | ||
| print(f"Available agents: {[a.id for a in (config.agents or [])]}") | ||
| print(f"Available teams: {[t.id for t in (config.teams or [])]}") | ||
| print(f"Available workflows: {[w.id for w in (config.workflows or [])]}") | ||
|
|
||
| # Get details about a specific agent | ||
| if config.agents: | ||
| agent_id = config.agents[0].id | ||
| agent = await client.get_agent(agent_id) | ||
| print("\nAgent Details:") | ||
| print(f" Name: {agent.name}") | ||
| print(f" Model: {agent.model}") | ||
| print(f" Tools: {len(agent.tools or [])}") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| asyncio.run(main()) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,135 @@ | ||
| """ | ||
| Running Agents with AgentOSClient | ||
|
|
||
| This example demonstrates how to execute agent runs using | ||
| AgentOSClient, including both streaming and non-streaming responses. | ||
|
|
||
| Prerequisites: | ||
| 1. Start an AgentOS server with an agent | ||
| 2. Run this script: python 02_run_agents.py | ||
| """ | ||
|
|
||
| import asyncio | ||
| import json | ||
|
|
||
| from agno.os.client import AgentOSClient | ||
|
|
||
|
|
||
| async def run_agent_non_streaming(): | ||
| """Execute a non-streaming agent run.""" | ||
| print("=" * 60) | ||
| print("Non-Streaming Agent Run") | ||
| print("=" * 60) | ||
|
|
||
| async with AgentOSClient(base_url="http://localhost:7777") as client: | ||
| # Get available agents | ||
| config = await client.get_config() | ||
| if not config.agents: | ||
| print("No agents available") | ||
| return | ||
|
|
||
| agent_id = config.agents[0].id | ||
| print(f"Running agent: {agent_id}") | ||
|
|
||
| # Execute the agent | ||
| result = await client.run_agent( | ||
| agent_id=agent_id, | ||
| message="What is 2 + 2? Explain your answer briefly.", | ||
| ) | ||
|
|
||
| print(f"\nRun ID: {result.run_id}") | ||
| print(f"Content: {result.content}") | ||
| print( | ||
| f"Tokens: {result.metrics.get('total_tokens') if result.metrics else 'N/A'}" | ||
| ) | ||
|
|
||
|
|
||
| async def run_agent_streaming(): | ||
| """Execute a streaming agent run.""" | ||
| print("\n" + "=" * 60) | ||
| print("Streaming Agent Run") | ||
| print("=" * 60) | ||
|
|
||
| async with AgentOSClient(base_url="http://localhost:7777") as client: | ||
| # Get available agents | ||
| config = await client.get_config() | ||
| if not config.agents: | ||
| print("No agents available") | ||
| return | ||
|
|
||
| agent_id = config.agents[0].id | ||
| print(f"Streaming from agent: {agent_id}") | ||
| print("\nResponse: ", end="", flush=True) | ||
|
|
||
| # Stream the response | ||
| full_content = "" | ||
| async for line in client.stream_agent_run( | ||
| agent_id=agent_id, | ||
| message="Tell me a short joke.", | ||
| ): | ||
| if line.startswith("data: "): | ||
| try: | ||
| data = json.loads(line[6:]) | ||
| if data.get("event") == "RunContent": | ||
| content = data.get("content", "") | ||
| print(content, end="", flush=True) | ||
| full_content += content | ||
| except json.JSONDecodeError as e: | ||
| print(f"Warning: Failed to decode JSON from line: {line[6:]}. Error: {e}") | ||
|
|
||
| print("\n") | ||
|
|
||
|
|
||
| async def run_agent_with_session(): | ||
| """Execute agent runs within a session for multi-turn conversations.""" | ||
| print("=" * 60) | ||
| print("Multi-Turn Conversation with Session") | ||
| print("=" * 60) | ||
|
|
||
| async with AgentOSClient(base_url="http://localhost:7777") as client: | ||
| # Get available agents | ||
| config = await client.get_config() | ||
| if not config.agents: | ||
| print("No agents available") | ||
| return | ||
|
|
||
| agent_id = config.agents[0].id | ||
|
|
||
| # Create a session for multi-turn conversation | ||
| session = await client.create_session( | ||
| agent_id=agent_id, | ||
| user_id="example-user", | ||
| ) | ||
| print(f"Created session: {session.session_id}") | ||
|
|
||
| # First message | ||
| print("\nUser: My name is Alice.") | ||
| result1 = await client.run_agent( | ||
| agent_id=agent_id, | ||
| message="My name is Alice.", | ||
| session_id=session.session_id, | ||
| ) | ||
| print(f"Assistant: {result1.content}") | ||
|
|
||
| # Second message - agent should remember the context | ||
| print("\nUser: What is my name?") | ||
| result2 = await client.run_agent( | ||
| agent_id=agent_id, | ||
| message="What is my name?", | ||
| session_id=session.session_id, | ||
| ) | ||
| print(f"Assistant: {result2.content}") | ||
|
|
||
| # Get session runs | ||
| runs = await client.get_session_runs(session_id=session.session_id) | ||
| print(f"\nSession has {len(runs)} runs") | ||
|
|
||
|
|
||
| async def main(): | ||
| await run_agent_non_streaming() | ||
| await run_agent_streaming() | ||
| await run_agent_with_session() | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| asyncio.run(main()) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| """ | ||
| Memory Operations with AgentOSClient | ||
|
|
||
| This example demonstrates how to manage user memories using | ||
| AgentOSClient. | ||
|
|
||
| Prerequisites: | ||
| 1. Start an AgentOS server with an agent that has enable_user_memories=True | ||
| 2. Run this script: python 03_memory_operations.py | ||
| """ | ||
|
|
||
| import asyncio | ||
|
|
||
| from agno.os.client import AgentOSClient | ||
|
|
||
|
|
||
| async def main(): | ||
| async with AgentOSClient(base_url="http://localhost:7777") as client: | ||
| user_id = "example-user" | ||
|
|
||
| print("=" * 60) | ||
| print("Memory Operations") | ||
| print("=" * 60) | ||
|
|
||
| # Create a memory | ||
| print("\n1. Creating a memory...") | ||
| memory = await client.create_memory( | ||
| memory="User prefers dark mode for all applications", | ||
| user_id=user_id, | ||
| topics=["preferences", "ui"], | ||
| ) | ||
| print(f" Created memory: {memory.memory_id}") | ||
| print(f" Content: {memory.memory}") | ||
| print(f" Topics: {memory.topics}") | ||
|
|
||
| # List memories for the user | ||
| print("\n2. Listing memories...") | ||
| memories = await client.list_memories(user_id=user_id) | ||
| print(f" Found {len(memories.data)} memories for user {user_id}") | ||
| for mem in memories.data: | ||
| print(f" - {mem.memory_id}: {mem.memory[:50]}...") | ||
|
|
||
| # Get a specific memory | ||
| print(f"\n3. Getting memory {memory.memory_id}...") | ||
| retrieved = await client.get_memory(memory.memory_id, user_id=user_id) | ||
| print(f" Memory: {retrieved.memory}") | ||
|
|
||
| # Update the memory | ||
| print("\n4. Updating memory...") | ||
| updated = await client.update_memory( | ||
| memory_id=memory.memory_id, | ||
| memory="User strongly prefers dark mode for all applications and websites", | ||
| user_id=user_id, | ||
| topics=["preferences", "ui", "accessibility"], | ||
| ) | ||
| print(f" Updated memory: {updated.memory}") | ||
| print(f" Updated topics: {updated.topics}") | ||
|
|
||
| # Get memory topics (optional - may fail if not supported) | ||
| print("\n5. Getting all memory topics...") | ||
| try: | ||
| topics = await client.get_memory_topics() | ||
| print(f" Topics: {topics}") | ||
| except Exception as e: | ||
| print(f" Skipped (endpoint may not be available): {type(e).__name__}") | ||
|
|
||
| # Get user memory stats (optional - may fail if not supported) | ||
| print("\n6. Getting user memory stats...") | ||
| try: | ||
| stats = await client.get_user_memory_stats() | ||
| print(f" Stats: {len(stats.data)} entries") | ||
| except Exception as e: | ||
| print(f" Skipped (endpoint may not be available): {type(e).__name__}") | ||
|
|
||
| # Delete the memory | ||
| print(f"\n7. Deleting memory {memory.memory_id}...") | ||
| await client.delete_memory(memory.memory_id, user_id=user_id) | ||
| print(" Memory deleted") | ||
|
|
||
| # Verify deletion | ||
| print("\n8. Verifying deletion...") | ||
| memories_after = await client.list_memories(user_id=user_id) | ||
| print(f" Remaining memories: {len(memories_after.data)}") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| asyncio.run(main()) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| """ | ||
| Session Management with AgentOSClient | ||
|
|
||
| This example demonstrates how to manage sessions using AgentOSClient. | ||
|
|
||
| Prerequisites: | ||
| 1. Start an AgentOS server with an agent | ||
| 2. Run this script: python 04_session_management.py | ||
| """ | ||
|
|
||
| import asyncio | ||
|
|
||
| from agno.os.client import AgentOSClient | ||
|
|
||
|
|
||
| async def main(): | ||
| async with AgentOSClient(base_url="http://localhost:7777") as client: | ||
| # Get available agents | ||
| config = await client.get_config() | ||
| if not config.agents: | ||
| print("No agents available") | ||
| return | ||
|
|
||
| agent_id = config.agents[0].id | ||
| user_id = "example-user" | ||
|
|
||
| print("=" * 60) | ||
| print("Session Management") | ||
| print("=" * 60) | ||
|
|
||
| # Create a session | ||
| print("\n1. Creating a session...") | ||
| session = await client.create_session( | ||
| agent_id=agent_id, | ||
| user_id=user_id, | ||
| session_name="My Test Session", | ||
| ) | ||
| print(f" Session ID: {session.session_id}") | ||
| print(f" Session Name: {session.session_name}") | ||
|
|
||
| # List sessions | ||
| print("\n2. Listing sessions...") | ||
| sessions = await client.list_sessions(user_id=user_id) | ||
| print(f" Found {len(sessions.data)} sessions") | ||
| for sess in sessions.data[:5]: # Show first 5 | ||
| print(f" - {sess.session_id}: {sess.session_name or 'Unnamed'}") | ||
|
|
||
| # Get session details | ||
| print(f"\n3. Getting session {session.session_id}...") | ||
| details = await client.get_session(session.session_id) | ||
| print(f" Agent ID: {details.agent_id}") | ||
| print(f" User ID: {details.user_id}") | ||
| print( | ||
| f" Runs: {len(details.runs) if hasattr(details, 'runs') and details.runs else 0}" | ||
| ) | ||
|
|
||
| # Run some messages in the session | ||
| print("\n4. Running messages in session...") | ||
| await client.run_agent( | ||
| agent_id=agent_id, | ||
| message="Hello!", | ||
| session_id=session.session_id, | ||
| ) | ||
| await client.run_agent( | ||
| agent_id=agent_id, | ||
| message="How are you?", | ||
| session_id=session.session_id, | ||
| ) | ||
|
|
||
| # Get session runs | ||
| print("\n5. Getting session runs...") | ||
| runs = await client.get_session_runs(session_id=session.session_id) | ||
| print(f" Found {len(runs)} runs in session") | ||
| for run in runs: | ||
| content_preview = ( | ||
| (run.content[:50] + "...") | ||
| if run.content and len(str(run.content)) > 50 | ||
| else run.content | ||
| ) | ||
| print(f" - {run.run_id}: {content_preview}") | ||
|
|
||
| # Rename session | ||
| print("\n6. Renaming session...") | ||
| renamed = await client.rename_session( | ||
| session_id=session.session_id, | ||
| session_name="Renamed Test Session", | ||
| ) | ||
| print(f" New name: {renamed.session_name}") | ||
|
|
||
| # Delete session | ||
| print(f"\n7. Deleting session {session.session_id}...") | ||
| await client.delete_session(session.session_id) | ||
| print(" Session deleted") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| asyncio.run(main()) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe make a helper file in this directory to spin up an AgentOS that would work for all the cookbooks