Skip to main content

Fareground

Agents SDK

Build agents with tools, conversations and streaming in Python.

CI Python 3.11+ PyPI Apache-2.0


Overview

The Agents SDK provides ask() for one-shot requests, Agent for conversations, and explicit engine components for application integration. Add tools, stream results, and choose in-memory, SQLite or PostgreSQL persistence.

Documentation · Quickstart · Tools · Production integration

It is the runtime layer in Fareground's family of open agent building blocks, alongside agent-id (identity), agent-messaging (encrypted agent-to-agent messaging), agent-memory (per-agent memory), and agent-knowledge (shared team knowledge).

What it deliberately does not do:

  • Authentication — your app verifies users. You hand the router an authenticator that turns each request into a tenant + user, and the framework enforces it: a caller only ever reaches its own tenant's sessions and memory, and the tenant comes from the authenticator, never the request body. (Omit it and the API runs as a single shared tenant for local/dev — it warns loudly so you never ship that by accident.)
  • The model — it talks to OpenAI, Anthropic, Google, and local models via Ollama. You bring the API key; pick any model at runtime, or let the framework detect a sensible default from your environment.
  • The frontend — you build the chat UI; the framework streams events to it.

Package names. The distribution is published as fg-agents and the import package is fg_agents (e.g. from fg_agents import create_app). These are the names dependents rely on and are intentionally left unchanged; the repository name is agents-sdk.

Install

The core install is deliberately slim — engine, tools, ask/Agent, and in-memory persistence. Everything else is an extra:

pip install fg-agents                 # core (engine + tools + in-memory persistence)
pip install "fg-agents[web]"          # + FastAPI app/router (create_app)
pip install "fg-agents[postgres]"     # + PostgreSQL backend (SQLAlchemy + asyncpg)
pip install "fg-agents[sqlite]"       # + SQLite backend
pip install "fg-agents[openai]"       # + OpenAI (and OpenAI-compatible) providers
pip install "fg-agents[anthropic]"    # + Anthropic provider
pip install "fg-agents[google]"       # + Google Gemini provider
pip install "fg-agents[all]"          # everything (web + postgres + sqlite + all providers + scheduler)
Extra Adds You need it for
(none) — ask/Agent, tools, engine, in-memory persistence
web fastapi, uvicorn create_app, create_agent_router, the HTTP/SSE API
postgres sqlalchemy, asyncpg PostgresRepository, memory="postgres:<url>"
sqlite aiosqlite SQLiteRepository, memory="sqlite"
anthropic / openai / google provider SDK that provider (openai also covers Ollama, Groq, and every other OpenAI-compatible provider)
scheduler croniter, sqlalchemy AgentScheduler

Requires Python 3.11+.

Quickstart

With one API key env var set (export ANTHROPIC_API_KEY=...) and the matching provider extra installed (pip install "fg-agents[anthropic]"), this is the whole program:

import asyncio

from fg_agents import ask


async def main():
    print(await ask("What's 2+2?"))


asyncio.run(main())

Already inside async code — or in a REPL with top-level await (python -m asyncio, IPython, Jupyter)? Then it's just:

print(await ask("What's 2+2?"))

ask() detects the provider from your environment — ANTHROPIC_API_KEY, then OPENAI_API_KEY, then GOOGLE_API_KEY/GEMINI_API_KEY, then a local Ollama server — and picks a current model for it. Pass model="provider:model" to override. It takes tools, a system prompt, and a memory backend too, and stream() is its streaming twin:

from fg_agents import ask, stream

answer = await ask("Greet Ada.", tools=[greet], system_prompt="Be friendly.")

async for event in stream("Tell me a story"):
    print(event.type, event.data)

If you might break out of a stream() loop early, wrap it in contextlib.aclosing(...) so the ephemeral agent is closed deterministically.

Conversations: the Agent facade

ask() is one-shot. For multi-turn conversations, the Agent facade is one object that wires the LLM client, tool registry, persistence, and engine — usable as an async context manager. Tools are plain functions; the schema is derived from the signature and docstring:

def greet(name: str) -> str:
    """Greet someone by name."""
    return f"Hello, {name}!"

async with Agent(
    tools=[greet],                    # model= optional — auto-detected
    system_prompt="You are a friendly greeter.",
    memory="sqlite",   # persist sessions; "memory" (default) or "postgres:<url>"
) as agent:
    first = await agent.run("Please greet Ada.")
    second = await agent.run("Now greet Grace.")  # same conversation

run() returns an AgentRunResult (.text, .session_id, .events — str() is the answer text), and agent.stream() yields raw StreamEvents as they happen. Any failure in run() — an engine error event or a raised exception — surfaces as a single AgentRunError carrying the session_id and the partial events, with the original exception chained as __cause__. Each Agent instance keeps one conversation by default; pass session_id= per call to target another.

Going lower level

The facade is sugar over four objects you can wire yourself when you need full control (custom middleware, skills, shared registries across agents). Graduate gradually via agent.engine, agent.llm, agent.tools, and agent.repository — or build the stack directly:

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}!"


async def main():
    llm = AgentLLM()
    repo = create_repository("memory")   # or "sqlite", "postgres"
    await repo.initialize()             # explicit here; the facade does this lazily

    tools = ToolRegistry()
    tools.register_function(greet)

    agent = AgentDefinition(
        name="greeter",
        model="anthropic:claude-sonnet-4-6",  # required — no default model
        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):
        if event.data.get("text"):
            print(event.data["text"], end="", flush=True)


asyncio.run(main())

A full web backend

create_app returns a FastAPI application exposing routes to start sessions, post messages, and stream replies over SSE.

from fg_agents import AgentDefinition, ToolRegistry, create_app, tool


@tool(description="Search the knowledge base")
async def search(query: str) -> str:
    return f"Results for '{query}'..."


assistant = AgentDefinition(
    name="assistant",
    model="anthropic:claude-sonnet-4-6",
    system_prompt="You are a helpful assistant. Use your tools to answer.",
    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",  # production
)
# uvicorn myapp:app

The frontend then creates a session and streams messages:

POST /api/agent/sessions                       -> { "session_id": "..." }
POST /api/agent/sessions/{id}/messages         -> text/event-stream (SSE)

See examples/ for five runnable apps, from a two-line facade hello-world to a complete chat UI (examples/04_web_app.py), plus frontend SSE clients in examples/frontend/.

Documentation

Start at docs/index.md for tutorials, concepts, provider setup, tools, hosting and troubleshooting.

Concepts / Building blocks

Building block What it is
Agent The facade — one object that wires LLM, tools, persistence, and engine; run() returns an AgentRunResult, failures raise AgentRunError.
AgentDefinition Declarative agent config — name, model, system prompt, tools, sub-agents. No default model; you choose the provider at runtime.
AgentEngine The ReAct loop: model → tools → model → …, emitting stream events at each step.
Orchestrator A coordinator agent that plans, delegates to sub-agents (in parallel), and synthesizes results.
Tools Python functions exposed to the agent via the @tool decorator and a ToolRegistry; built-in tools ship in tools/builtin.py.
Skills Reusable bundles of prompt templates + tools that give an agent domain knowledge (SkillsManager).
Memory WorkingMemory per-session scratch space and a ContextManager with health scoring and progressive compression.
Middleware Hooks into the agent loop: audit, token tracking, permissions, rate limiting, loop guarding, context compression.
Persistence Async repositories behind one interface — InMemoryRepository, SQLiteRepository, PostgresRepository via create_repository(...).
Streaming StreamEvent objects serialized to SSE (event.to_sse()) with reconnection support.
Scheduler Run an agent on a cron schedule (AgentScheduler, optional croniter dependency).
API layer create_app / create_agent_router — FastAPI integration with pluggable authentication and per-tenant isolation.
flowchart TB
    User([User in browser])
    subgraph Framework["Agent"]
        direction TB
        Skills["Skills<br/><sub>knowledge & playbooks</sub>"]
        Tools["Tools<br/><sub>actions the agent can take</sub>"]
        Subs["Sub-agents<br/><sub>specialists to delegate to</sub>"]
    end
    DB[("Your database<br/><sub>sessions, history</sub>")]
    LLM([Any model<br/>OpenAI · Anthropic · local])

    User <-->|SSE stream| Framework
    Framework <--> Skills
    Framework <--> Tools
    Framework <--> Subs
    Framework <--> LLM
    Framework <--> DB

Project structure

src/fg_agents/
    agent.py       Agent facade — one-object setup (quickstart tier)
    core/          Engine, LLM client, types, errors
    tools/         @tool decorator, registry, built-in tools, handlers
    orchestrator/  Multi-agent orchestration + sub-agent runner
    skills/        Skill loading and injection
    memory/        Working memory, context management, health scoring
    middleware/    Audit, token tracking, permissions, rate limit, loop guard
    persistence/   Multi-backend: in-memory, SQLite, PostgreSQL
    streaming/     SSE event definitions
    prompts/       System prompt construction
    scheduler/     Cron-scheduled agents
    api/           Service layer, FastAPI router, auth, schemas
    app.py         create_app() application factory
examples/          Five runnable apps + frontend SSE clients
docs/              Reference docs: API, streaming wire format, persistence
tests/             Test suite

Contributing

Development setup, tests, linting, and commit conventions live in CONTRIBUTING.md. See the changelog for what's changed.


Built by Fareground.
Licensed under Apache-2.0.

Metadata

Release files for fg-agents 0.4.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fg-agents 0.4.6
File Size Uploaded
fg_agents-0.4.6.tar.gz 230.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fg-agents 0.4.6
File Interpreter ABI Platform
fg_agents-0.4.6-py3-none-any.whl Python 3 none any Details

Total release size: 396.0 kB

Release files / fg_agents-0.4.6.tar.gz

Download URL fg_agents-0.4.6.tar.gz
Size 230.2 kB
Tags Source
SHA-256 checksum
How to use checksums
13a88a093159b2757535795fad859a9d810f2417f95e9290927c262ca18fa415
BLAKE2b-256 checksum
How to use checksums
2856715cd2aea15cd923ff6a8e48a75120cd82bc3007723d7fcef8571c06a4b1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.

Transparency log

Release files / fg_agents-0.4.6-py3-none-any.whl

Download URL fg_agents-0.4.6-py3-none-any.whl
Size 165.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fe05b44be1927e3a0a36b4e2fbac2444a9870e7e476e00c05b9b6a043183640c
BLAKE2b-256 checksum
How to use checksums
077dfc2cdcf3d5a1ebdf2314c4ef13d1b9726edc314f3d6c92862bdbfb29de28
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.

Transparency log

Release history Release notifications | RSS feed

0.4.7

2 release files

This release

0.4.6 This release

2 release files

0.4.5

2 release files

0.4.4

2 release files

0.4.3

2 release files

0.4.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page