Skip to main content

Lattis

Run AI agents on a server, interact from anywhere.

I built an agent I liked (Binsmith) and wanted to use it from my laptop, my phone, wherever. Lattis is what emerged: a server that hosts agents with a TUI for terminals and a web UI for browsers.

I run it on a Linux box in my Tailscale network. Start a conversation on my laptop, pick it up on my phone, everything stays in sync.

Quick start

# Run the TUI (starts a local server automatically)
uvx lattis

# Or run the server explicitly, then connect from anywhere
uvx lattis server

Open http://localhost:8000 for the web UI, or run uvx lattis from another machine pointing at your server.

What you get

  • Server + clients: FastAPI backend, Textual TUI, bundled web UI
  • Persistent conversations: threads stored in SQLite, survive restarts
  • Pluggable agents: different agents per thread, swap anytime
  • Works anywhere: if it can hit HTTP, it can use your agents

The setup I use

┌─────────────────────────────────────────────────────────────┐
│                    Linux server (Tailscale)                 │
│                      lattis server                          │
│                           :8000                             │
└─────────────────────────────────────────────────────────────┘
        ▲                    ▲                    ▲
        │                    │                    │
   ┌────┴────┐         ┌─────┴─────┐        ┌────┴────┐
   │  laptop │         │   phone   │        │  tablet │
   │   TUI   │         │  web UI   │        │  web UI │
   └─────────┘         └───────────┘        └─────────┘

Threads persist on the server. I can start something on my laptop, continue on my phone, come back to it days later.

Agents

Lattis discovers agents automatically from:

  1. Built-ins: assistant, poetry (included with Lattis)
  2. Entry points: any installed package that registers with lattis.agents
  3. Explicit specs: module:attr paths via --agents or AGENT_PLUGINS

Binsmith is what started all this. Now it's just another plugin:

uv pip install binsmith
uvx lattis --agent binsmith

Building your own agent

The simplest case - just export a pydantic-ai Agent:

# my_agent.py
from pydantic_ai import Agent

plugin = Agent("google-gla:gemini-2.0-flash", system_prompt="You are helpful.")
uvx lattis --agents my_agent:plugin

For more control (custom dependencies, lifecycle hooks), use the plugin API:

from pydantic_ai import Agent
from lattis.plugins import AgentPlugin, AgentRunContext

def create_agent(model: str) -> Agent:
    return Agent(model, system_prompt="...")

def create_deps(ctx: AgentRunContext):
    # Access ctx.workspace, ctx.project_root, ctx.session_id, etc.
    return MyDeps(...)

plugin = AgentPlugin(
    id="my-agent",
    name="My Agent",
    create_agent=create_agent,
    create_deps=create_deps,
)

Register via entry point in pyproject.toml:

[project.entry-points."lattis.agents"]
my-agent = "my_package:plugin"

CLI

lattis                 # TUI (default)
lattis tui             # TUI explicitly
lattis server          # API server + web UI

TUI options

--server <url>     Connect to a remote server
--local            Skip server discovery, run in-process
--agent <id>       Default agent (local mode)
--agents <specs>   Extra plugins to load (local mode)

The TUI auto-discovers a server on localhost:8000 if one is running for the same project. Use --server to point at a remote machine.

Server options

--host <host>      Interface to bind (default: 127.0.0.1)
--port <port>      Port (default: 8000)
--reload           Auto-reload on code changes
--agent <id>       Default agent
--agents <specs>   Extra plugins to load

TUI commands

/help                     Show help
/threads                  List threads
/thread <id>              Switch to thread (creates if needed)
/thread new [id]          Create new thread
/thread delete <id>       Delete thread
/clear                    Clear current thread
/agent                    Show current agent
/agent list [filter]      List available agents
/agent set <id>           Switch agent for this thread
/model                    Show current model
/model list [filter]      List available models
/model set <name>         Switch model
/quit                     Exit

Storage

.lattis/
  lattis.db          # SQLite - threads, messages, state
  session_id         # Persistent session identifier
  workspace/         # Shared directory for agents that need it

Configuration

Variable Default Description
AGENT_DEFAULT assistant Default agent
AGENT_PLUGINS Extra plugins (comma-separated module:attr)
LATTIS_SERVER_URL Server URL for remote connections
LATTIS_PROJECT_ROOT cwd Project root for storage
LATTIS_DATA_DIR .lattis Data directory
LATTIS_WORKSPACE_DIR Override workspace location

Requirements

  • Python 3.12+
  • uv (recommended)
  • An API key for at least one model provider (Gemini, Anthropic, OpenAI)
export GEMINI_API_KEY=...     # Google
export ANTHROPIC_API_KEY=...  # Anthropic
export OPENAI_API_KEY=...     # OpenAI

Web UI development

The web UI is bundled from frontend/. To rebuild:

cd frontend
npm install
npm run build

Static files are served from lattis/web/static when present.

Metadata

Release files for lattis 0.6.1

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

Built distribution (wheel)

Table of built distributions (wheels) for lattis 0.6.1
File Interpreter ABI Platform Actions
lattis-0.6.1-py3-none-any.whl Python 3 none any Details for lattis-0.6.1-py3-none-any.whl

Release files / lattis-0.6.1-py3-none-any.whl

Download URL lattis-0.6.1-py3-none-any.whl
Size 212.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
75f13e3df1fa982f90b5fd867fefebb4535ffb8ca82b565bae7dec9784f04d9a
BLAKE2b-256 checksum
How to use checksums
db07d2b115b87d2a35172e0feec092aac04dd4defa0347325f66def511041d26
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.9.22 {"installer":{"name":"uv","version":"0.9.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for lattis 0.6.1

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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