gligabao.ServeOptions that gligabao calls at defined points. This page lists every hook that is available to external code.
Not a callback, but also supplied by the embedding program: admin UI extensions (
ServeOptions.AdminExtensions) add views and UI to the admin page.
Everything else (the remember queue, the stores, the LLM clients) lives under internal/ and is not part of the public API; it cannot be hooked from outside the module.
System events
Types
gligabao.Hooks and gligabao.SystemEvent are aliases of the types in the monitoring package, which is outside internal/ so it can also be imported directly.
Behaviour
- Installed for the lifetime of
Serve.ServeinstallsServeOptions.Hookswhen it starts and removes them when it returns. There is no way to add or remove a hook while the server runs. - Several hook sets.
ServeOptions.Hooksis a list; every set is called for each event, in the order of the list. Anilfield is skipped. With no hook installed, events are dropped. - Synchronous. The callback runs on the goroutine that handles the request, before the HTTP response is written, so a slow callback slows the response. Keep it fast; hand slow work (network calls) to a goroutine or a buffered queue. (
gligabao_intdoes this for its BetterStack sink.) - Concurrent. Requests are handled concurrently, so the callback must be safe for concurrent use.
- Read-only event. The
SystemEventmap must not be modified, and should not be retained after returning if you may change it: copy it first. - Panics are contained. A callback that panics does not affect the request or stop the remaining callbacks; the panic is silently discarded, so recover and log yourself if you want to know.
ctxis the context of the HTTP request that caused the event (cancelled if the client leaves).- Events are emitted by the regular endpoints and by their
evalvariants (POST /v1/gb/eval/remember,POST /v1/gb/eval/query), which use the same handlers.
Event types
eventType is <operation>.completed or <operation>.failed. Events carry counts and sizes, never the content (no text, query or answer). Values are string, int or int64.
Fields common to all events: user_id, dataset, duration_ms (int64). A .failed event also has error (the error message, string).
remember.completed
A text was remembered (POST /v1/gb/remember with text).
remember.failed
The text pipeline failed (the request returned 502; nothing is stored).
Fields: user_id, dataset, session_id, remember_run_id (the run in gb_remember_runs, see Remember manager), text_bytes, duration_ms, error.
remember_image.completed
An image was read (POST /v1/gb/remember with image).
Fields: user_id, dataset, image_artifact_id, session_id, extraction_id, media_type, image_bytes, theme, text_blocks (text blocks read), duration_ms.
remember_image.failed
Fields: user_id, dataset, session_id, image_bytes, duration_ms, error.
query.completed
A question was answered (POST /v1/gb/query).
Fields: user_id, dataset, session_id, query_bytes, evidence_entities, evidence_edges (the size of the evidence returned), duration_ms.
query.failed
Fields: user_id, dataset, session_id, query_bytes, duration_ms, error. It is emitted for any error of the query, including those answered with 400/404 (invalid user or dataset, dataset not found), not only 502.
timeseries.completed
Series were stored (POST /v1/gb/timeseries).
Fields: user_id, dataset, series (number stored), duration_ms.
timeseries.failed
Fields: user_id, dataset, series (number in the request), duration_ms, error. Only emitted for a server error (500); an anchor that cannot be resolved (422) and other client errors emit nothing.
Example: metrics and alerts
systemEventHook in gligabao_int/gligabao_int/options.go.
Stability
The event types and field names above are what the server emits now. New fields may be added to an event, and new event types may be added, in any release: ignore what you do not know, and read fields with a checked type assertion (v, ok := ev["x"].(int)). A change to or removal of an existing event or field is called out in the changelog.
Timeseries providers
A provider is a callback,Fetch, with which remember pulls timeseries from a source of the embedding program’s, for the entities an LLM decides it covers. It is registered with ServeOptions.TimeseriesProviders:
Contract, in short:
Fetch is called concurrently, with a 60 s timeout per call, must honour ctx, may return no series and no error when it has nothing, and a panic in it is caught and reported as an error. The providers are validated when Serve starts and it returns the error for a malformed one. Full description, validation rules and the request side: Timeseries.
Trained model deployers
A deployer is a callback,Deploy, that receives a trained model’s weights, as files in a directory on the local disk, and does with them whatever the embedding program wants: upload them to a service, copy them somewhere, convert them. gligabao does not know or care what; it only fetches the files and records the outcome. The full description of how deploying works is in Model deploying. Deployers are registered with ServeOptions.TrainedModelDeployers:
POST /v1/gb/training/models/{id}/deployments and a body {"deployer": "bucket", "options": {...}}; options is a free-form JSON object that reaches the callback unchanged (req.Options). It is available in training mode (--training) only, like the rest of the training API.
Behaviour
- gligabao fetches the files; the deployer does not. The weights live on the sidecar’s storage (Modal: the models volume). Before calling the deployer gligabao downloads every file of
Model.Filesfrom the sidecar (GET /models/file, see Sidecar training API) intoDir, and checks each against its recorded size and sha256. The deployer gets files that are complete and verified, and never talks to the sidecar. Diris an absolute path,<trained model deploy dir>/<job id>(serve --trained-model-deploy-dir,ServeOptions.TrainedModelDeployDir, defaulttrained_modelsnext to the database file). The files are at the pathsModel.Fileslists, relative to it (adapter_config.json,adapter_model.safetensors,tokenizer.model, …). gligabao never deletes it: it is kept for later deployments of the same model, which find the files in place (verified again) and download only what is missing or damaged. Clean it up yourself. The deployer must treat it as read only; copy or archive what it needs.- Synchronous. The request that asked for the deployment waits for the fetch and then for
Deploy; its HTTP response is the stored deployment. Fetching a large model and a slow upload can take minutes: callers must not use a short timeout.ctxis the request’s context (cancelled if the client leaves), soDeployshould honour it. - Result. On success
Refidentifies what the deployer made, in its own terms (e.g. the name of the uploaded model), andDetailsis anything else worth keeping; it must be JSON-encodable. Both are stored and returned with the deployment. - Failure. An error returned by
Deploy(or a panic, which is caught) marks the deploymentfailedwith the error text and answers502. So does a failure to fetch the files. A failed deployment is not retried by gligabao. - Concurrent. Requests are handled concurrently, so
Deploymust be safe for concurrent use, also for the same model.DeployIDis unique to each call: use it if the deployer needs a unique name. - Recorded. Every deployment that reaches the fetch is stored in
gb_trained_model_deployments(statusrunning, thencompletedorfailed; the deployer, its options, the directory,ref,details, the error, the duration) and listed byGET /v1/gb/training/models/{id}/deployments. A row stillrunninglong after it started was interrupted (the server restarted). - Validated at startup.
Servereturns an error for a deployer with noDeploy, aNamethat is not 1-64 letters, digits,_,-or.(starting with a letter or digit), or a duplicate name. At most 20. - System events. Each deployment emits
training.model_deploy.completedortraining.model_deploy.failedto theSystemEventhook, withmodel_id,deploy_id,deployer,duration_ms(int64) and, on failure,error.