docs / agent-framework / getting started

Getting started

Install

Requires Python 3.11+. The core install already includes FastAPI, uvicorn, SQLAlchemy (async), and asyncpg — a PostgreSQL-backed web deployment needs no extras.

pip install fg-agents                 # core (FastAPI + PostgreSQL/asyncpg)
pip install "fg-agents[sqlite]"       # + SQLite backend (aiosqlite)
pip install "fg-agents[openai]"       # + OpenAI provider (covers all OpenAI-compatible)
pip install "fg-agents[anthropic]"    # + Anthropic provider
pip install "fg-agents[google]"       # + Google Gemini (google-genai)
pip install "fg-agents[templates]"    # + Jinja2 for prompt templates
pip install "fg-agents[scheduler]"    # + croniter for cron scheduling
pip install "fg-agents[all]"          # everything

Note: some ImportError messages mention pip install "fg-agents[postgres]", but no postgres extra exists — asyncpg is a core dependency, so PostgreSQL works out of the box.

Imports guarded by optional dependencies (SQLiteRepository, AgentScheduler, the web/API symbols, …) resolve to None or raise a clear error until the matching extra is installed.

API keys

Keys are resolved in two ways, in order:

  1. An explicit override: AgentLLM(api_keys={"openai": "sk-...", ...})
  2. Environment variables named {PROVIDER}_API_KEY — e.g. OPENAI_API_KEY, ANTHROPIC_API_KEY.

Local providers (Ollama, LM Studio, vLLM, …) need no key. One environment gate matters: the CODE tool type is disabled unless FG_ALLOW_CODE_EXECUTION=true is set — and even then it is not a security sandbox.

Hello agent — one agent, streamed, no database

import asyncio
from fg_agents import (
    AgentDefinition, AgentEngine, AgentLLM, ToolRegistry, create_repository, tool,
)

@tool(description="Greet someone by name")
def greet(name: str) -> str:
    return f"Hello, {name}! Welcome to Fareground."

async def main():
    llm = AgentLLM()
    repo = create_repository("memory")      # or "sqlite", "postgres"
    await repo.initialize()

    tools = ToolRegistry()
    tools.register_function(greet)

    agent_def = AgentDefinition(
        name="greeter",
        model="ollama:qwen3:8b",            # required — there is no default
        system_prompt="You are a friendly greeter. Use the greet tool when asked.",
        tools=["greet"],
    )

    engine = AgentEngine(llm=llm, tool_registry=tools, repository=repo)
    async for event in engine.run("session-1", "Say hello to Alice", agent_def):
        if event.data.get("text"):
            print(event.data["text"], end="", flush=True)
        elif event.type.value == "tool.result":
            print(f"\n  [tool] {event.data['tool_name']}: {event.data['status']}")

asyncio.run(main())

What each piece does:

A full web backend in one call

create_app() wires the whole stack — orchestrator, repository, router, SSE — into a FastAPI application:

from fg_agents import AgentDefinition, ToolRegistry, create_app, tool

@tool(description="Search the knowledge base")
async def search(query: str) -> str: ...

assistant = AgentDefinition(
    name="assistant",
    model="anthropic:claude-sonnet-4-6",
    system_prompt="You are the product assistant.",
    tools=["search"],
)

tools = ToolRegistry()
tools.register_function(search)

app = create_app(
    agents={"assistant": assistant},
    tool_registry=tools,
    # db_url="postgresql+asyncpg://user:pass@localhost:5432/mydb",  omitting db_url falls back to a SQLite file (fg_agents.db), not in-memory
)
# run with: uvicorn myapp:app

The HTTP surface (default prefix /api/agent):

Method Path Purpose
POST /sessions Create a session → { session_id }
GET /sessions/{id} Session status and metadata
DELETE /sessions/{id} Delete a session
POST /sessions/{id}/messages Send a message → SSE stream (or JSON with stream=false)
POST /sessions/{id}/cancel Nuclear stop (cascades to sub-agents)
POST /sessions/{id}/resume Resume a waiting_input / failed session
GET /sessions/{id}/stream Re-attach to an in-flight run (Last-Event-ID replay)
GET /sessions/{id}/messages Paginated history (limit / offset)
GET /sessions/{id}/artifacts Session artifacts
GET /sessions/{id}/audit Audit log
GET / POST /tools List tools / register tool (POST admin-gated)
GET / POST /agents List agents / register agent (POST admin-gated)
GET /memory/{agent_id} Agent persistent memory
PUT /memory/{agent_id}/{key} Set a memory key
GET /health Health check

Runs are owned by a process-wide run registry and detached from the HTTP request — a client disconnect does not cancel the agent; the browser re-attaches via GET /sessions/{id}/stream.

Without an authenticator, the app runs as a single shared admin tenant and logs a loud one-time warning — fine for local development, never for production. See the multi-tenant security model.

Where to go next