agentpaas.md 9.7 KB

AgentPaaS Platform Documentation

AgentPaaS is a Platform-as-a-Service for deploying, managing, and running Lambda-calculus-based AI agents. It wraps the lambdagent DSL with a multi-tenant API server, persistent sessions, provider management, and monitoring.


Architecture Overview

                    CLI / HTTP Client
                          |
                    ┌─────▼─────┐
                    │  FastAPI   │   agentpaas/src/agentpaas/api/app.py
                    │  Server    │   (serve --dev)
                    └─────┬─────┘
                          |
           ┌──────────────┼──────────────┐
           |              |              |
    ┌──────▼──────┐ ┌────▼────┐ ┌───────▼───────┐
    │ Agent CRUD  │ │ Auth /  │ │ Status /      │
    │ + Execution │ │ Tenant  │ │ Metrics       │
    └──────┬──────┘ └─────────┘ └───────────────┘
           |
    ┌──────▼──────────────────────┐
    │   lambdagent Engine         │
    │   (Compiler + Runtime)      │
    │                             │
    │   YAML → Lambda Term → CEK  │
    │   ConversationLam (session) │
    └──────┬──────────────────────┘
           |
    ┌──────▼──────────────────────┐
    │   Unified Provider System   │
    │                             │
    │   claude-code  (no API key) │
    │   anthropic    (API key)    │
    │   ollama       (local)      │
    │   openai       (API key)    │
    │   dashscope    (API key)    │
    └─────────────────────────────┘

Key components:

  • FastAPI Server (agentpaas serve) — REST API with multi-tenant auth, SSE streaming, OpenAPI docs at /docs.
  • Agent Store — SQLite/Postgres-backed CRUD for agent configs, versions, run history.
  • lambdagent Engine — Compiles YAML into Lambda terms, executes via CEK machine with ReAct loops, tool routing, and beta-reduction tracing.
  • ConversationLam — Session-persistent Lambda abstraction that maintains conversation history across turns.
  • Unified Provider System — Five core providers with automatic detection and YAML-based switching.

Agent Lifecycle

1. Create

Define an agent via YAML config and deploy to the platform:

# Write YAML config
cat > my-agent.yml <<'EOF'
agentId: my-agent
name: MyAgent
type: react
model:
  provider: claude-code
  name: sonnet
systemPrompt: "You are a helpful research assistant."
react:
  maxSteps: 10
EOF

# Lint before deploying
python -m lambdagent lint my-agent.yml

# Deploy to PaaS
python -m agentpaas agent create --name my-agent --config my-agent.yml
# Output: Agent created: ag_abc123

2. Deploy

The agent is live immediately after agent create. The PaaS server compiles the YAML into a Lambda term at execution time, so no build step is needed. The API endpoint is:

POST /api/v1/agents/{agent_id}/run
POST /api/v1/agents/{agent_id}/run/stream   (SSE)

3. Chat (Interactive)

Use agentpaas chat for interactive multi-turn conversation:

agentpaas chat my-agent

The chat command resolves the agent by name (fuzzy match) or ID, opens an interactive session with SSE streaming, and maintains conversation context server-side.

With provider: claude-code in the YAML config, no API key is required -- the agent calls Claude Code CLI directly.

4. Update

Iterate on the agent config with automatic versioning:

# Edit config, then update
python -m agentpaas agent update ag_abc123 --config my-agent-v2.yml --changelog "Added search tools"

# View version history
python -m agentpaas agent versions ag_abc123

# Rollback if needed
python -m agentpaas agent rollback ag_abc123 --version 1

Each update increments the version. If the config content is unchanged, no new version is created.


Provider Configuration

AgentPaaS uses a unified provider system. The provider is specified in the agent's YAML config under model.provider:

Provider Type API Key Required Notes
claude-code Claude Code CLI No Uses Claude Code Max Plan subscription
anthropic Anthropic API Yes (ANTHROPIC_API_KEY) Direct API access
ollama Local inference No Requires ollama serve running locally
openai OpenAI API Yes (OPENAI_API_KEY) GPT models
dashscope Alibaba Cloud Yes (DASHSCOPE_API_KEY) Qwen models

Provider in YAML

model:
  provider: claude-code   # Switch provider here
  name: sonnet            # Model name (provider-specific)
  temperature: 0.0

Provider detection priority

When provider is not specified, the system auto-detects:

  1. If model name has a known prefix (e.g., dashscope/qwen-max), use that provider.
  2. If model name matches known patterns (e.g., claude-* -> anthropic, gpt-* -> openai).
  3. Fall back to environment variable detection.

Managing providers via CLI

# List providers and status
python -m agentpaas provider list

# Test a provider connection
python -m agentpaas provider test anthropic

# Add/configure a provider
python -m agentpaas provider add dashscope --api-key sk-xxxx

Session Persistence via ConversationLam

ConversationLam is the core mechanism for multi-turn conversation support. It wraps any LLMProvider with conversation history management.

Lambda semantics

ConversationLam(provider, prompt) = lambda x. provider(history ++ [x])

Each apply() call:

  1. Appends the input as a user message to the history.
  2. Calls the provider with the full conversation (or windowed subset).
  3. Records the assistant response.
  4. Returns the response.

Key difference from stateless Lam

Lam ConversationLam
State Stateless -- each call is independent Stateful -- builds on all previous calls
History None Full message list with windowing
Use case Single-shot tasks Multi-turn chat, ReAct loops

Configuration

from lambdagent.conversation import ConversationLam
from lambdagent.providers.claude_code_provider import ClaudeCodeProvider

provider = ClaudeCodeProvider(config)
lam = ConversationLam(
    name="agent",
    provider=provider,
    system_prompt="You are a helpful assistant.",
    max_history_tokens=80000,   # Token window limit
    keep_recent_turns=20,       # Minimum recent turns to keep
)

r1 = lam.apply("read the README")       # Creates conversation
r2 = lam.apply("[tool result] ...")       # Continues with full memory
r3 = lam.apply("summarize what we did")   # Still remembers r1, r2

This is what eliminates hallucination in multi-step ReAct agents: the LLM sees its complete conversation history, not a lossy compressed state string.


MCP Isolation: --strict-mcp-config

By default, agents inherit globally available MCP tools. The --strict-mcp-config flag (or strictMcpConfig: true in YAML) enables MCP isolation: the agent can only access tools explicitly declared in its own config.

strictMcpConfig: true
mcp:
  onlineTool:
    my-server:
      - search
      - read_file
  localTools:
    - terminate

This is important for multi-tenant deployments where agents should not access each other's tools.


API Endpoints Overview

All endpoints are under /api/v1/ and require an API key header (X-API-Key).

Agents

Method Path Description
POST /agents Create agent
GET /agents List agents
GET /agents/{id} Get agent details
PUT /agents/{id} Update agent config
DELETE /agents/{id} Delete agent (soft)
POST /agents/{id}/rollback Rollback to version
GET /agents/{id}/versions List versions

Execution

Method Path Description
POST /agents/{id}/run Execute agent (sync)
POST /agents/{id}/run/stream Execute agent (SSE streaming)
GET /agents/{id}/runs List run history
POST /agents/{id}/runs/record Record external run

Auth & Tenants

Method Path Description
POST /auth/keys Create API key
GET /auth/keys List API keys
DELETE /auth/keys/{id} Revoke API key
POST /admin/tenants Create tenant
GET /admin/tenants/{id} Get tenant
PUT /admin/tenants/{id}/quota Update quota

Monitoring

Method Path Description
GET /status Platform overview
GET /status/agents All agents status
GET /status/agents/{id} Single agent status
GET /status/agents/{id}/health Health score
GET /metrics/overview Platform metrics
GET /billing/usage Usage/billing data

Traces

Method Path Description
GET /traces/{run_id} Get run trace
GET /traces/{run_id}/tools Get tool calls
POST /traces/{run_id}/confirm Confirm tool action

Other

Method Path Description
GET /health Server health check
GET /.well-known/agent.json Agent discovery
GET /jobs/{id} Async job status
POST /jobs/{id}/cancel Cancel async job