Zeta · Assistants
Every tool an assistant can be granted, whether it can actually run, and which of your team assistants holds it.
Every assistant is Zeta at work — one AI, under your rules
Tools
16
in the closed catalog
Runnable
16
have an implementation
Granted but unrunnable
0
none — a grant means a capability
Steps per run
6
hard ceiling
| Tool | What it does | Scope | Changes data | Ceiling | Runs |
|---|---|---|---|---|---|
| model.complete | Send a prompt to the configured model, or the deterministic local fallback. | none needed | no | 120/h · 5000/day | yes |
| knowledge.search | Retrieve passages from the organisation’s indexed documents. | documents | no | 120/h · 5000/day | yes |
| crm.read | Look up leads, contacts, companies and opportunities. | leads | no | 120/h · 5000/day | yes |
| crm.write | Create or update a CRM record. | leads | yes | 30/h · 500/day | yes |
| tasks.write | Add a task for a human to pick up. | tasks | yes | 30/h · 500/day | yes |
| reports.read | Read generated reports and their underlying aggregates. | reports | no | 120/h · 5000/day | yes |
| systems.read | Read system health, checks and incidents. | systems | no | 120/h · 5000/day | yes |
| alerts.write | Raise an alert or notification to a human. | alerts | yes | 30/h · 500/day | yes |
| revenue.opportunities.read | Read open opportunities ranked by the documented priority model, with the evidence for each score. | opportunities | no | 120/h · 5000/day | yes |
| revenue.quality.read | Aggregate counts of what the customer's data can and cannot support. No personal records. | reports | no | 120/h · 5000/day | yes |
| revenue.attribution.read | What followed a campaign — contacted, influenced, converted. Never a revenue claim. | reports | no | 120/h · 5000/day | yes |
| revenue.campaigns.read | Read reactivation campaigns, their targets and their outcomes. | reports | no | 120/h · 5000/day | yes |
| revenue.campaigns.write | Propose a reactivation campaign over dormant opportunities. Creates a PROPOSAL only — no work exists until a person approves it. | opportunities | yes | 30/h · 500/day | yes |
| dial.queues.read | Read call queues and how much work is waiting in them. | queues | no | 120/h · 5000/day | yes |
| medical.cohortpatient data | Read counts across the patient panel — recall states, reactivation windows, responsiveness. Counts only; no patient is identified. | patients | no | 30/h · 400/day | yes |
| medical.recallpatient data | Start recall outreach across a cohort. Each patient is resolved and gated server-side; the agent names a population, never a person. | patients | yes | 4/h · 20/day | yes |
The catalog is a closed list. An assistant platform where tools register themselves at runtime can tell you what its assistants happened to do, never what they are able to do. The “Runs” column is the one that was missing until Phase 6: a permission is only meaningful if something exists behind it. The ceilings are Phase 7’s, and they are enforced beside the scope check rather than in the assistant loop — a limit the loop applies is a limit a scheduled job does not have.
Populations, never people
Both Medical tools return counts. There is no tool that returns a patient — no list, no lookup, not even a redacted one. An assistant asks to start recall outreach over a cohort; the patients are resolved inside the executor and never reach the model. No argument on any tool accepts a patient identifier.
It acts as its owner
An assistant has no PHI grant of its own and cannot be given one. It reaches patient data only while its owner holds a live grant, and the access log records AI_WORKER acting for that person — not the person. Revoke the owner’s grant and every assistant they deployed stops on its next call.
Scanned on the way out
Every Medical observation is scanned for PHI-shaped content before the model sees it, and a hit throws rather than redacting. A redaction that half-works ships a leak with a green build. This check is expected never to fire; that is what it is for.
Medical will not read patient data until it can encrypt it — for an assistant exactly as for a person. The Medical tools above decline for that reason, which is the behaviour an auditor would ask for.
No team assistants deployed.
A team assistant holds the scopes its role allows, narrowed further if you choose. Deploy one to see what it could reach.
A disabled team assistant can call nothing, whatever it was granted. A gated team assistant stops at its first data-changing call and leaves it pending — the action is described and not performed, rather than performed and reported afterwards.
- knowledge.search: Retrieve passages from the organisation’s indexed documents. Arguments: query: string — what to search the documents for - crm.read: Look up leads, contacts, companies and opportunities. Arguments: entity: enum (contacts|companies|leads) — which records to read; limit?: number — how many rows - crm.write: Create or update a CRM record. Arguments: action: enum (create_contact|log_activity) — what to write; firstName?: string — contact first name; lastName?: string — contact last name; email?: string — contact email; contactId?: string — contact the activity concerns; subject?: string — activity subject; body?: string — activity detail CHANGES DATA. - tasks.write: Add a task for a human to pick up. Arguments: title: string — what needs doing; description?: string — detail; dueInDays?: number — days until due CHANGES DATA. - reports.read: Read generated reports and their underlying aggregates. No arguments. - systems.read: Read system health, checks and incidents. Arguments: entity?: enum (systems|incidents) — systems or incidents - alerts.write: Raise an alert or notification to a human. Arguments: subject: string — what is wrong; severity?: enum (INFO|WARNING|CRITICAL) — how bad; detail?: string — supporting detail CHANGES DATA. - revenue.opportunities.read: Read open opportunities ranked by the documented priority model, with the evidence for each score. Arguments: view?: enum (priority|dormant|health) — priority for the ranked worklist, dormant for stale deals only, health for pipeline totals; minDaysDormant?: number — only deals untouched for at least this many days (dormant starts at 21); minAmount?: number — only deals worth at least this many dollars; limit?: number — how many rows - revenue.quality.read: Aggregate counts of what the customer's data can and cannot support. No personal records. No arguments. - revenue.attribution.read: What followed a campaign — contacted, influenced, converted. Never a revenue claim. Arguments: campaignId: string — the campaign to report on - revenue.campaigns.read: Read reactivation campaigns, their targets and their outcomes. Arguments: campaignId?: string — one campaign to look at in detail; omit for a list of all of them - revenue.campaigns.write: Propose a reactivation campaign over dormant opportunities. Creates a PROPOSAL only — no work exists until a person approves it. Arguments: name: string — a short name for this campaign, for the person who will review it; minDaysDormant?: number — how stale a deal must be to be included; minAmount?: number — minimum deal value in dollars; limit?: number — how many accounts to include, at most; callableOnly?: enum (yes|no) — yes to include only accounts with a phone number, which is what a calling campaign needs CHANGES DATA. - dial.queues.read: Read call queues and how much work is waiting in them. No arguments. - medical.cohort: Read counts across the patient panel — recall states, reactivation windows, responsiveness. Counts only; no patient is identified. Arguments: view: enum (lapse|reactivation|panel|responsiveness) — which population summary to read: lapse (recall states), reactivation (how long since last visit), panel (overall practice figures), or responsiveness (how fast inbound requests are answered) - medical.recall: Start recall outreach across a cohort. Each patient is resolved and gated server-side; the agent names a population, never a person. Arguments: campaign: string — a name for this recall campaign, for the outreach record; purpose: enum (treatment|payment|operations|marketing|fundraising|research) — the HIPAA purpose. Recall for care due is treatment; anything promotional is marketing and needs written authorization on file; channel: enum (call|sms|email|mail|portal) — how to reach them; state?: enum (due|overdue|lapsed) — which recall state to act on. Defaults to overdue.; limit?: number — how many patients at most (ceiling 25) CHANGES DATA.
Generated from the executors, so it cannot drift from what the runtime accepts. A model is shown only the tools the team assistant actually holds; a call to anything else is refused by name and fed back, so the assistant can try something it is allowed to do rather than failing the whole run.
A provider is configured, so these 15 tools are also sent as JSON Schema through the provider's own tool-calling protocol. Until Phase 7 the model was asked to “reply with JSON only” and the reply was parsed. That fails silently: a model that wraps its JSON in a sentence produces a parse error indistinguishable from an assistant with nothing to do. A structured tool call is a better request — it is not permission, and everything below still applies to it.
Scope, then arguments
Authorisation runs before the tool. Arguments are then validated against a declared schema, and any field the schema does not name is dropped — including the one a model invents most often, an organisation identifier.
6 steps, then stop
An assistant that cannot finish stops and says so. An unbounded planner against a paid model is an unbounded bill, and against a free one an infinite loop nobody is watching.
Every attempt is a row
Permitted and denied alike. An assistant repeatedly reaching for something it cannot have is the most useful signal in the registry, and swallowing it throws that away.