Configure the service for the admin. Pick one `action`; only the fields relevant to that action are needed (supplying extras is harmless, but a required field must be present).
- `setup_telegram_bot` — persist a Telegram bot token so the service can receive messages through the bot and send back replies. Pass the `token` from BotFather (the `NNN:AAA...` string). The token is validated live via getMe and saved, and the Telegram listener hot-reloads it immediately — no restart is required. Next step: use `bind_telegram` to bind the admin's `@username`, then ask the admin to send `/start` to the bot.
- `bind_telegram` — bind the admin's own Telegram `@username` so incoming bot messages are routed to them. Pass the `handle` with or without the leading `@` (it is normalized — a leading `@` is stripped). Admin-only: it always operates on the single admin account. The handle must not already be bound to another user — if it is, the tool refuses rather than silently reassigning it. The handle "unknown" is reserved (Telegram reports username-less senders under it) and the tool refuses to bind it.
- `add_workspace` — register a workspace (a project directory to manage) and switch the admin's active workspace to it. Pass a short unique `name` (used in ticket ids and the GUI) and the absolute `path` to the project directory.
- `add_user` — create a guest account and bind them to Telegram. Pass the user's display `name` and their Telegram `@username` (the `telegram` handle, with or without the leading `@`). The tool refuses the admin's own name — the name is the admin marker, so only guest accounts can be created. The handle "unknown" is reserved and cannot be bound. The tool refuses a Telegram handle already bound to a different user.
- `setup_web_search` — register a web-search backend so agents can use `web_search`. Pass the `provider` — `firecrawl` or `exa` — and its API `key`. The provider and its matching key are persisted. Once registered, agents that support web search (e.g. the Assistant) can call `web_search` immediately.
Custom tools are authored as script files in the `shared` folder of the admin's personal workspace; a tool is referenced everywhere by its file name without the extension, and it becomes available to another user only by being granted to them.
- `grant_tool` — grant one custom tool to a user. Pass the user's name as `user` and the tool's name as `tool` (the file name without its extension of a script in the `shared` folder of the admin's personal workspace). Granting a tool the user already has is a no-op.
- `revoke_tool` — revoke one custom tool from a user. Pass `user` and `tool` as for `grant_tool`. Revoking a grant the user does not have is a no-op.
- `list_grants` — show the custom-tool grants as recorded. Pass `user` to list that user's grants, or omit it to list every user that has any. Grants are listed even when the granted tool's file no longer exists in `shared`, so the list reflects what was recorded, not what currently works.