Skip to main content

Run your application

Reboot applications are defined using an instance of Application, and launched from the file configured as your --application in .rbtrc.

Application

Your entrypoint will construct an Application and then run it:

async def main():
await Application(
servicers=[ChatRoomServicer],
initialize=initialize,
).run()


if __name__ == '__main__':
asyncio.run(main())

initialize functions

The optional initialize argument to the Application constructor is a function that runs every time your application starts up.

Initializers can be used to create any initial state that your application needs. In particular, they are usually where any singleton instances used by your application are created.

async def initialize(context: InitializeContext):
chat_room = ChatRoom.ref(EXAMPLE_STATE_MACHINE_ID)

# Implicitly construct state machine upon first write.
await chat_room.send(
context,
message="Hello, World!",
)

If you have declared an initialize function, then you can additionally pass an initialize_bearer_token (initializeBearerToken in TypeScript). That token is used to construct the context passed to initialize, so that the calls initialize makes are authenticated to your application.

Signing users in

Pass an OAuth to have Reboot run an OAuth server for your application — the sign-in flow for browsers, native apps, and AI MCP clients alike, plus User auto-construction:

from reboot.aio.auth.oauth import OAuth
from reboot.aio.auth.oauth_providers import (
Development,
Google,
OAuthProviderByEnvironment,
)

application = Application(
servicers=[UserServicer, CounterServicer],
oauth=OAuth(
provider=OAuthProviderByEnvironment(
dev=Development(),
prod=Google(...),
),
allowed_origins=["https://app.example.com"],
),
)
await application.run()

An application whose API declares a User type must configure this; starting without it is an error rather than a silent fallback. To verify tokens minted somewhere else instead, see Bearer tokens.

Presenting your app

Three optional arguments describe your application to the clients that connect to it — most visibly MCP clients and the setup wizard your app serves at its root URL:

ArgumentDescription
titleA human-readable name. Defaults to the application name.
descriptionWhat the application does, in a sentence.
example_promptsExamplePrompts that give a first-time visitor something to try.

The MCP endpoint

Application mounts an MCP endpoint at /mcp, so any MCP client can connect. Methods declared with mcp=Tool() appear there as tools, and UI methods as tools plus resources. No extra configuration is needed in your main.py.

HTTP custom routes

Using a Reboot Application you can not only run your Reboot servicers but you can also provide custom HTTP route handlers for circumstances where you can't just call one of your data type's methods.

For Python, this is implemented using FastAPI. For TypeScript, this is implemented with Express.js.

important

Limitations of custom HTTP routes

  • Currently only GET and POST methods are supported.

  • The / route is currently used by Reboot itself to show a helpful page explaining that this is a Reboot application.

Reach out at [email protected] if you run into use cases for fixing these!

Here is an example of implementing a handler for an HTTP GET:

@application.http.get("/hello_world")
def hello_world():
return {"message": "Hello, world!"}

To simplify calling directly into your Reboot application from your application.http.get and application.http.post handlers, Reboot provides a context of type ExternalContext, because you are still "external" to your application from an authorization perspective.

This context includes any bearer token from Authorization: Bearer <token> so that any calls into your Reboot application will be properly authorized. In TypeScript, the context is injected into every handler. In Python, Reboot follows the FastAPI dependency injection strategy: if you want the context, you must explicitly add it to your handler's arguments as shown in the following example:

@application.http.post("/hello_greeter")
async def hello_greeter(
request: Request,
context: ExternalContext = InjectExternalContext,
):
body = await request.json()
greeter, _ = await Greeter.create(
context,
title=body['title'],
name=body['name'],
adjective=body['adjective'],
)

response = await greeter.greet(context, name="You")

return {"message": response.message}