agents,
wired together.
Define an agent, decorate a few @tool methods, pick a strategy. The container resolves the llm, the tools, and the session scopes — you just run it.
base classes
subclass AgentBase, set a prompt, ship.
strategies
react, plan-and-execute, supervisor — swap freely.
@tool decorator
turn any async function into an agent tool.
wired through DI
vector stores, services, sessions — all injected.
Strategy
ReAct Executor
Agent Core
Data Analyst Agent
Injected Tool
Postgres Query Engine
the whole backend, ready when you are.
Type-safe end to end. Zero globals. Async at every layer. The patterns that hold up at 100k lines start working on line one.
type-safe to the edges.
Full container inference. Your IDE knows what exists, what's wired, and what's missing — no guessing, no surprises.
async, end to end.
Container, modules, controllers — concurrency-safe by construction. Not an add-on, the foundation.
lifecycle you trust.
Providers boot in priority order. Shutdown is clean. Resources never leak.
one unified ecosystem.
Web, AI, SQL, events, tasks, auth, cache, search — all wired through one container, all built around one rule. Pick a few, ship the thing.
a small core, a wide family.
Every package talks through contracts. Mix the ones you need; the rest stay out of your way.
lexigram-web
async routing and controllers, DI-native.
lexigram-ai
agents, llms, rag, mcp — one entry point.
lexigram-sql
sqlalchemy sessions and unit-of-work.
lexigram-search
full-text and vector search, one contract.
lexigram-auth
JWT, OAuth, and policies — wired in.
lexigram-events
event bus over your broker of choice.
early on purpose.
Lexigram is in 0.1 — which means you can still change it. APIs may shift before 1.0, so pin your versions, and tell us what feels wrong. Shaping a framework is more fun when it's still soft.
why it grows with you.
The patterns that get you to a working demo on Sunday are the same patterns that still hold up at 100k lines. Declare what you need; the container resolves the rest.
wiring by hand
Couplings hide everywhere; small changes ripple.
service = UserService(
PostgresRepo(),
RedisCache(),
EmailClient(
smtp_host="localhost"
)
) # ❌ Brittle at scale- Dependencies spread across the codebase
- Hidden coupling between components
- A change in one place breaks another
wired through DI
Say what you need. The container does the rest.
class UserService:
def __init__(
self,
repo: UserRepository,
cache: Cache
): ...
# ✅ Container resolves it
service = await container.resolve(UserService)- Contracts, never implementations
- Type-safe end to end
- Swapping an implementation is one line
the moving parts.
Lexigram revolves around one container and a handful of well-named seams. Once you know them, the rest fits.
where bindings live
class DatabaseProvider(Provider):
name = "database"
priority = ProviderPriority.INFRASTRUCTURE
async def register(self, container: ContainerRegistrarProtocol) -> None:
container.singleton(DatabaseProtocol, PostgresDatabase)
async def boot(self, container: BootContainerProtocol) -> None:
db = await container.resolve(DatabaseProtocol)
await db.connect()ship something this weekend.
Two installs and a dozen lines. Boot the app, hit the route, watch it work.
$ pip install lexigram lexigram-webfrom lexigram import Application
from lexigram.web import WebProvider
app = Application(name="hello")
app.add_provider(WebProvider())
@app.controller()
class HelloController:
@get("/hello")
async def hello(self) -> dict:
return {"message": "Hello, Lexigram"}
if __name__ == "__main__":
app.run()
Build with
Lexigram
Whether you're moving a legacy monolith toward something cleaner or starting fresh on a weekend project, we'd love to hear from you. Sign up for early access, framework updates, or enterprise support.