Basketball Demo
Minimal end-to-end Orchid example: GenericAgents with built-in tool classes, PostgreSQL storage, cross-agent skills, and an event-driven trivia agent.
What this demonstrates
The basketball demo is Orchid's "hello world". It wires two chat-facing GenericAgent instances — an NBA stats expert and a sports psychologist — using built-in tools implemented as OrchidTool subclasses in the example's Python package, plus the PostgreSQL storage backend provided by the orchid-storage-postgres plugin. A third agent, trivia_generator, is activated by the example's Pollen + Bloom schedule to produce a weekday morning trivia digest. No MCP servers, no external APIs, and no custom agent classes are required — the agent definitions live in agents.yaml.
Run it
git clone https://github.com/gadz82/orchid-examples
cd orchid-examples/basketball
cp .env.example .env
docker compose up --buildThis starts the API (http://localhost:8080), the web UI (http://localhost:3000), PostgreSQL, Qdrant, and the MCP gateway. Ollama runs on your host with llama3.2 and nomic-embed-text (plus minicpm-v for document uploads).
Configuration walkthrough
orchid.yml sets the runtime environment — LLM, storage backend, and pointer to agent configs:
# orchid.yml (trimmed)
agents:
config_path: examples/basketball/agents.yaml
llm:
model: ollama/llama3.2
ollama_api_base: http://host.docker.internal:11434
auth:
dev_bypass: true # skip identity check for local dev
storage:
class: orchid_storage_postgres.OrchidPostgresChatStorage
dsn: postgresql://orchid:${POSTGRES_PASSWORD}@postgres:5432/orchid
# ...truncatedAgent configs define the agents, their tools, the cross-agent skills, and the morning-trivia event wiring:
# agents.yaml (trimmed)
version: "1"
defaults:
llm:
model: "ollama/llama3.2"
temperature: 0.2
rag:
enabled: false
tools:
get_player_stats:
class: "examples.basketball.tools.basketball.GetPlayerStatsTool"
description: "Get stats for an NBA player (points, rebounds, assists, team, position)"
compare_players:
class: "examples.basketball.tools.basketball.ComparePlayersTool"
description: "Side-by-side comparison of two NBA players with advantage analysis"
assess_motivation:
class: "examples.basketball.tools.psychology.AssessMotivationTool"
description: "Assess a player's motivation level, drive type, and risk factors"
# ...truncated
skills:
player_performance_review:
description: "Get a player's stats then assess their motivation"
steps:
- agent: basketball
instruction: "Look up the player's current stats and performance data"
- agent: psychologist
instruction: "Assess their motivation and suggest mental strategies"
agents:
basketball:
description: "NBA basketball expert with player stats and roster tools."
prompt: |
You are a Basketball Expert AI assistant. Provide insightful
basketball analysis using the stats from your tools.
tools: [get_player_stats, compare_players, get_team_roster]
psychologist:
description: "Sports psychologist for motivation and team dynamics."
prompt: |
You are a Sports Psychologist specialized in basketball performance.
tools: [assess_motivation, suggest_mental_strategy, analyze_team_dynamics]
trivia_generator:
description: "Event-driven agent that produces the morning trivia digest."
tools: [get_player_stats, get_team_roster]
# ...truncatedWhat to look for
storage.class: orchid_storage_postgres.OrchidPostgresChatStorage→ theorchid-storage-postgresplugin provides chat persistence; any importableOrchidChatStoragesubclass can be plugged in here, and the framework resolves it via dotted import at startup.tools.<name>.class→ built-in tools areOrchidToolsubclasses referenced by dotted path; plain Python functions referenced withhandler:are also supported.skills.player_performance_review.steps→ a cross-agent skill chains two agents in sequence; the supervisor executes each step in order and passes context forward.events.schedules+events.triggers→ a weekday cron schedule activates the event-driventrivia_generatoragent. See Pollen + Bloom.defaults.rag.enabled: false→ RAG is disabled globally; individual agents can override this per-field.auth.dev_bypass: true→ skips identity resolution for local development; remove this in production.