I’m experiencing an issue where os.agno.com
connects successfully to my localhost AgentOS instance but doesn’t maintain user sessions across chat messages. Each POST request creates a new session instead of reusing the existing one.
Setup:
- AgentOS running on
http://localhost:7777
- Connecting from
os.agno.com
to localhost - Using standard AgentOS implementation with user session middleware
- CORS properly configured with
https://os.agno.com
in allowed origins
What’s Working:
os.agno.com
connects successfully (green light, “connected” status)
Can see agents and send/receive messages
GET requests work properly and reuse sessions
Direct browser access to
localhost:7777
maintains sessions perfectly
The Problem:
Every chat message (POST to
/agents/{agent}/runs
) creates a new user session
No conversation memory between messages
POST requests from
os.agno.com
contain no cookies (Cookie
header missing)
Technical Details:
Request Headers (POST from os.agno.com):
Origin: https://os.agno.com
Cookie: [missing]
Response Headers (from localhost):
Set-Cookie: user_id=...; Max-Age=2592000; Path=/; SameSite=Lax
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://os.agno.com
Browser Cookies:
- Cookies for
agno.com
domain: Present - Cookies for
localhost:7777
domain: Missing
The Issue:
The browser is not storing cookies set by the localhost server when requests come from os.agno.com
. This appears to be related to cross-origin cookie handling between HTTPS (os.agno.com
) and HTTP (localhost:7777
).
Question:
Is there a specific configuration or cookie setting required for os.agno.com
to properly handle user sessions with localhost AgentOS instances? Other users seem to use this setup successfully, so I’m wondering if there’s something I’m missing.
Environment:
- Browser: [Your browser]
- OS: Ubuntu
- AgentOS: Latest version
- Python: 3.12
Code:
#!/usr/bin/env python3
"""
AgentOS Server - Optimized Performance with Cirkelline Personal Assistant
"""
import os
import uuid
import time
from typing import Dict, Any
from agno.agent import Agent
from agno.db.postgres import PostgresDb
from agno.models.google import Gemini
from agno.os import AgentOS
from agno.tools.duckduckgo import DuckDuckGoTools
from agno.tools.exa import ExaTools
from agno.tools.tavily import TavilyTools
from agno.tools.googlesearch import GoogleSearchTools
from agno.tools.reasoning import ReasoningTools
from fastapi import Request, Response
from fastapi.middleware.cors import CORSMiddleware
from utils.api_key_manager import api_key_manager
# Database configuration
start_time_db = time.time()
DATABASE_URL = os.getenv(
"DATABASE_URL",
"postgresql+psycopg://postgres:VEMKc9HJU1px87i7AtBt@cirkelline-db.crm4mi2uozbi.eu-north-1.rds.amazonaws.com:5432/cirkelline-db"
)
db = PostgresDb(db_url=DATABASE_URL)
print(f"Startup: Database connection initialized in {time.time() - start_time_db:.2f} seconds")
# Search tools initialization
start_time_tools = time.time()
search_tools = [
ReasoningTools(),
DuckDuckGoTools(timeout=90, fixed_max_results=2),
ExaTools(),
TavilyTools(),
GoogleSearchTools(),
]
print(f"Startup: Search tools initialized in {time.time() - start_time_tools:.2f} seconds")
# Create a single default agent for AgentOS initialization
def create_default_agent() -> Agent:
return Agent(
name="Cirkelline",
model=Gemini(
id="gemini-2.5-flash",
api_key=api_key_manager.get_key_for_component("main_agent")
),
db=db,
user_id="default",
tools=search_tools,
description="""You are Cirkelline, a warm and thoughtful personal assistant created by kv1nt.
You're like a close friend who genuinely cares about the person you're helping - someone who
remembers the little details, asks about their day, and provides support with a personal touch.""",
instructions=[
"Be conversational and friendly - like talking to a good friend over coffee",
"Remember and reference previous conversations naturally - 'How did that meeting go?' or 'Still working on that project?'",
"Ask thoughtful follow-up questions about their day, mood, or ongoing situations",
"Show genuine interest in their life - celebrate wins, offer support during challenges",
"Use their name when you know it, and remember personal details they share",
"Be proactive - suggest things, offer reminders, or check in on past topics",
"Keep responses warm but concise - like a friend who listens well and speaks thoughtfully",
"When appropriate, share observations or gentle advice based on what you know about them"
],
# Enable memory features
enable_user_memories=True,
enable_session_summaries=True,
add_history_to_context=True,
add_datetime_to_context=True,
markdown=True,
exponential_backoff=True,
delay_between_retries=2,
retries=5,
)
# Cache for user agents to avoid recreation
user_agents_cache: Dict[str, Dict[str, Agent]] = {}
def get_user_agents(user_id: str) -> Dict[str, Agent]:
"""Get or create agents for a specific user (with caching)"""
if user_id not in user_agents_cache:
start_time_create_agents_total = time.time()
start_time_cirkelline_agent = time.time()
cirkelline_agent_instance = Agent(
name="Cirkelline",
model=Gemini(
id="gemini-2.5-flash",
api_key=api_key_manager.get_key_for_component("main_agent")
),
db=db,
user_id=user_id,
tools=search_tools,
description="""You are Cirkelline, a warm and thoughtful personal assistant created by kv1nt.
You're like a close friend who genuinely cares about the person you're helping - someone who
remembers the little details, asks about their day, and provides support with a personal touch.""",
instructions=[
"Be conversational and friendly - like talking to a good friend over coffee",
"Remember and reference previous conversations naturally - 'How did that meeting go?' or 'Still working on that project?'",
"Ask thoughtful follow-up questions about their day, mood, or ongoing situations",
"Show genuine interest in their life - celebrate wins, offer support during challenges",
"Use their name when you know it, and remember personal details they share",
"Be proactive - suggest things, offer reminders, or check in on past topics",
"Keep responses warm but concise - like a friend who listens well and speaks thoughtfully",
"When appropriate, share observations or gentle advice based on what you know about them"
],
# Enable memory features
enable_user_memories=True,
enable_session_summaries=True,
add_history_to_context=True,
add_datetime_to_context=True,
markdown=True,
exponential_backoff=True,
delay_between_retries=2,
retries=5,
)
print(f"Request: Cirkelline agent for user {user_id[:8]}... created in {time.time() - start_time_cirkelline_agent:.2f} seconds")
start_time_research_agent = time.time()
research_specialist_instance = Agent(
name="Research Specialist",
model=Gemini(
id="gemini-1.5-pro",
api_key=api_key_manager.get_key_for_component("research_team_1")
),
db=db,
user_id=user_id,
tools=search_tools,
enable_user_memories=True,
role="Expert at finding and analyzing information with a friendly, helpful approach",
markdown=True,
add_datetime_to_context=True,
exponential_backoff=True,
delay_between_retries=2,
retries=5,
)
print(f"Request: Research specialist agent for user {user_id[:8]}... created in {time.time() - start_time_research_agent:.2f} seconds")
user_agents_cache[user_id] = {
"cirkelline_personal_assistant": cirkelline_agent_instance,
"research_specialist": research_specialist_instance
}
print(f"Request: Total agents for user {user_id[:8]}... created in {time.time() - start_time_create_agents_total:.2f} seconds")
return user_agents_cache[user_id]
# Initialize AgentOS with default agent
start_time_agentos_init = time.time()
agent_os = AgentOS(
os_id="cirkelline-os",
description="Cirkelline - Your personal assistant",
agents=[create_default_agent()],
)
app = agent_os.get_app()
print(f"Startup: AgentOS app initialized in {time.time() - start_time_agentos_init:.2f} seconds")
# CORS configuration
CORS_ALLOW_ORIGINS_LIST = os.getenv("CORS_ALLOW_ORIGINS_LIST")
if CORS_ALLOW_ORIGINS_LIST:
allowed_origins = [origin.strip() for origin in CORS_ALLOW_ORIGINS_LIST.split(',')]
else:
allowed_origins = [
"https://cirkelline-chat.vercel.app",
"https://chat.cirkelline.com",
"http://localhost:3000",
"https://os.agno.com",
]
app.add_middleware(
CORSMiddleware,
allow_origins=allowed_origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# User session middleware for proper user isolation
@app.middleware("http")
async def user_session_middleware(request: Request, call_next):
start_time_middleware = time.time()
# Skip user session logic for OPTIONS requests (CORS preflight)
if request.method == "OPTIONS":
response = await call_next(request)
return response
# Get or create user_id
user_id = request.cookies.get("user_id")
if not user_id:
user_id = str(uuid.uuid4())
print(f"🌐 New Cirkelline session: {user_id[:8]}...")
else:
print(f"🔄 Existing Cirkelline session: {user_id[:8]}...")
# Store user_id in request state
request.state.user_id = user_id
request.state.user_agents = get_user_agents(user_id)
response = await call_next(request)
# Set cookie if new user
if not request.cookies.get("user_id"):
if request.url.hostname == "localhost" or request.url.hostname == "127.0.0.1":
# Localhost development settings
response.set_cookie(
key="user_id",
value=user_id,
httponly=False,
samesite="Lax",
secure=False,
max_age=30*24*60*60, # 30 days
path="/"
)
else:
# Production settings
response.set_cookie(
key="user_id",
value=user_id,
httponly=True,
samesite="Lax",
secure=True,
max_age=30*24*60*60, # 30 days
path="/"
)
print(f"Request: Processed for user {user_id[:8]}... in {time.time() - start_time_middleware:.2f} seconds")
return response
# Health endpoint
@app.get("/health")
async def health_check():
start_time_health = time.time()
response = {"status": "healthy", "timestamp": time.time()}
print(f"Request: Health check responded in {time.time() - start_time_health:.2f} seconds")
return response
# Override agent selection to use user-specific agents
@app.middleware("http")
async def agent_override_middleware(request: Request, call_next):
"""Override the default agent with user-specific agents"""
if hasattr(request.state, 'user_agents') and request.url.path.startswith('/v1/'):
# Replace the default agents with user-specific ones
agent_os.agents = list(request.state.user_agents.values())
# CRITICAL: Set the user_id for all agents to match the session user_id
for agent in agent_os.agents:
agent.user_id = request.state.user_id
response = await call_next(request)
return response
if __name__ == "__main__":
import uvicorn
print("🌐 CIRKELLINE - Your Personal Assistant")
print(f"🔑 API Keys: {api_key_manager.get_key_count()} (Capacity: {api_key_manager.get_total_capacity()} req/min)")
print("✨ Personal memories and thoughtful conversations")
print("💝 Created by kv1nt with care")
print("📍 Frontend: http://localhost:3000")
uvicorn.run("agentos_server:app", host="0.0.0.0", port=7777)
Any guidance would be greatly appreciated!