Skip to main content
Author the lightweight code plugin types — routes, middleware, lifecycle handlers, and pooled clients. These four are the smallest kinds of extension. Three of them — routes, middleware, and lifecycle handlers — share one pattern: a module the manifest imports, plus a registration decorator that runs on import. The fourth — a pooled client — is a code helper you open from within one of those modules. All register through the tai42_app handle and depend on tai42-contract only.
These are server-side code plugins — they run in the Python process. To extend the browser workbench instead — contribute pages, tool panels, or sidebar nav entries to the Studio shell — see Author a Studio plugin.

Routes

Add an HTTP route with @tai42_app.http.custom_route. It registers a Starlette handler and its self-describing OpenAPI metadata in one call — summary, tags, and response_model are required so the route describes itself to the API reference.
examples/code_plugins/routes.py
Load the module under routers_modules. A packaged plugin can also ship this route as a router item in its tai-plugin.yml, so the marketplace installer wires it in.

Middleware

Add ASGI middleware with @tai42_app.http.middleware, which registers the middleware onto the app’s stack.
manifest.yml
A packaged plugin can also ship middleware as a middleware item in its tai-plugin.yml.

Lifecycle handlers

Run code at process startup, shutdown, or after an in-place reload. Register a handler with @tai42_app.lifecycle.on_startup, on_shutdown, or on_reload. An on_reload handler re-runs after every reload — use it for dynamic loaders that on_startup ran once.
examples/code_plugins/lifecycle.py
Load the module under lifecycle_modules. This is also how import-only registrations — a webhook verifier, a connector provider — reach the process.

Pooled clients

A pooled client shares one connection per event loop across tool calls. Subclass the kit’s PooledClient (which implements the BaseClient contract), then open it through tai42_app.clients.client_ctx from inside a tool, route, or lifecycle handler. The context manager yields a connected client, pooled per loop and connection params (or one-shot with fresh=True).
examples/code_plugins/pooled_client.py
A client is not wired by a manifest field of its own — it rides into the process through whichever module imports it, and is opened via client_ctx at call time.

See also