Getting Started¶
Installation¶
Or with uv:
Create a Namespace¶
Define your methods and register them with api tags:
# myapp/api.py
from lythonic.compose.namespace import Namespace
from pydantic import BaseModel
class GreetIn(BaseModel):
name: str
class GreetOut(BaseModel):
message: str
def greet(input: GreetIn) -> GreetOut:
"""Greet someone by name."""
return GreetOut(message=f"Hello, {input.name}!")
ns = Namespace()
ns.register(greet, nsref="greet", tags=["api"])
Configure the Server¶
Create data/woodglue.yaml, pointing at the namespace object:
A namespace can also be declared in its own YAML file
(myapp: {file: myapp_ns.yaml}) or inline (myapp: {entries: [...]}); see
woodglue.config.NamespaceEntry.
Start the Server¶
Get the Auth Token¶
Auth is enabled by default (auth.enabled in woodglue.yaml). The server
keeps Users, Role assignments, and tokens in data/auth.db. On first start it
creates a token for the built-in admin User, which holds every Grant.
wgl start never prints it. To see or rotate it:
wgl token # print the admin token
wgl token --new # replace it; the running server picks it up immediately
Sign In to the Console¶
Open http://127.0.0.1:5321/. It sends you to the login page; paste the admin
token. The Console shows the namespaces, runs, and triggers you may see, and a
Tokens page for your own Personal Access Tokens. To let people sign in with
their own accounts, configure an Identity Provider: see
Identity Providers.
Give Others Access¶
Define Roles and give them to Users. For a script, create a Service User and issue it a Personal Access Token:
wgl user add ci
wgl user assign ci reporter
wgl user issue ci nightly --days=90 # prints the secret once
See Control who can do what for Grants, Roles, and tokens.
For a remote server, sign in through the browser instead; the token is
stored for that server and used by WoodglueClient:
Call via JSON-RPC¶
curl -X POST http://127.0.0.1:5321/rpc \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $(wgl token)" \
-d '{"jsonrpc":"2.0","method":"myapp.greet","params":{"input":{"name":"World"}},"id":1}'
Use the Async Client¶
from pathlib import Path
from woodglue.client import WoodglueClient
client = WoodglueClient("http://127.0.0.1:5321", data_dir=Path("data"))
await client.load_spec(strict=True)
result = await client.call("myapp.greet", input={"name": "World"})
# result is GreetOut(message="Hello, World!")