Skip to content

← Back to YouLab

Guide for contributing to and developing YouLab.

  • Python 3.11+
  • uv package manager
  • Running Letta server (for integration testing)

Terminal window
# Clone the repository
git clone <repo-url>
cd YouLab
# Run setup (installs deps + pre-commit hooks)
make setup

This installs:

  • All project dependencies
  • Development tools (pytest, ruff, basedpyright)
  • Pre-commit hooks for automatic verification

src/youlab_server/
├── agents/ # BaseAgent, templates, registry
├── memory/ # Memory blocks and strategies
├── pipelines/ # OpenWebUI Pipe integration
├── server/ # FastAPI HTTP service
│ └── strategy/ # Strategy agent endpoints
├── observability/ # Logging and tracing
├── config/ # Settings management
└── main.py # CLI entry point
tests/
├── conftest.py # Shared fixtures
├── test_memory.py # Memory block tests
├── test_templates.py # Agent template tests
├── test_pipe.py # Pipeline tests
└── test_server/ # HTTP service tests
├── test_endpoints.py
├── test_agents.py
└── test_strategy/

Edit files in src/youlab_server/.

Terminal window
make lint-fix

Important: Run this after every file edit to catch issues early.

Terminal window
# Quick check (lint + typecheck)
make check-agent
# Full verification (lint + typecheck + tests)
make verify-agent

Commits are automatically blocked if checks fail. The hooks run make verify before each commit.


YouLab uses the “swallow success, show failure” pattern from HumanLayer:

CommandWhat It Does
make check-agentLint + typecheck with minimal output
make test-agentTests only, fail-fast
make verify-agentFull verification suite

On success: Minimal output like ✓ Ruff check, ✓ Typecheck

On failure: Full error output for debugging


  1. Define the template in agents/templates.py:
MY_TEMPLATE = AgentTemplate(
type_id="my-agent",
display_name="My Agent",
description="What this agent does",
persona=PersonaBlock(
name="MyAgent",
role="Specific role",
capabilities=["Capability 1", "Capability 2"],
tone="professional",
verbosity="concise",
),
)
  1. Register in the registry:
# In agents/default.py or where registry is configured
from youlab_server.agents.templates import MY_TEMPLATE
registry.register(MY_TEMPLATE)
  1. Add tests in tests/test_templates.py.
  1. Add schema in server/schemas.py:
class MyRequest(BaseModel):
field: str
class MyResponse(BaseModel):
result: str
  1. Add endpoint in server/main.py:
@app.post("/my-endpoint", response_model=MyResponse)
async def my_endpoint(request: MyRequest) -> MyResponse:
# Implementation
return MyResponse(result="...")
  1. Add tests in tests/test_server/test_endpoints.py.
  1. Extend block in memory/blocks.py:
class HumanBlock(BaseModel):
# Existing fields...
new_field: str | None = None
  1. Update to_memory_string() serialization.

  2. Add tests in tests/test_memory.py.


Create a .env file:

Terminal window
cp .env.example .env

Minimum configuration:

# Required
ANTHROPIC_API_KEY=your-key
# Letta connection
LETTA_BASE_URL=http://localhost:8283
# Service settings (optional)
YOULAB_SERVICE_HOST=127.0.0.1
YOULAB_SERVICE_PORT=8100

Terminal window
pip install letta
letta server
Terminal window
uv run youlab-server
Terminal window
uv run youlab

LOG_LEVEL=debug
  1. Set Langfuse credentials in .env
  2. Visit your Langfuse dashboard
  3. Filter by user_id or agent_id
IssueSolution
Letta connection failedEnsure letta server is running
Type errorsRun make typecheck for details
Import errorsRun uv sync to update deps

  • Use type annotations everywhere
  • Prefer composition over inheritance
  • Keep functions focused and small
  • Document non-obvious behavior
TypeConventionExample
ClassesPascalCaseAgentManager
Functionssnake_caseget_agent
ConstantsUPPER_SNAKEDEFAULT_PORT
Private_prefix_cache

Organized by ruff:

  1. Standard library
  2. Third-party
  3. First-party (youlab_server)