Skip to content
1,050 linesCodeBlameRaw

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

Chat and workspace agents: channels, DMs and named agents you talk to1/**
2 * A workspace's own agents: named members with a job, a personality,
3 * routing limits and a budget, kept by the agents service
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)4 * (`services/agents`). Every workspace also has `@g1t`, its built-in
The docs folder is gone, and what it held lives where people read it: how a self-hosted g1t runs and how to deploy g1t to Cloudflare are pages on docs.g1t.sh under Run g1t yourself, and speed, rate limits and operating g1t.sh are sections of CONTRIBUTING.md; code that cited a file in docs/ now points to the page or section that covers it, or says what it means itself, and applied migrations and the runner images are left as they were.5 * orchestrator, kept the same way (`builtin`).
Chat and workspace agents: channels, DMs and named agents you talk to6 *
7 * Wire shapes are snake_case end to end.
8 */
9import type { ServiceBinding } from "./clients";
10import type { Role, User } from "./identity";
11import type { Result } from "./result";
Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar12import type { CardActionResult } from "./chat";
Chat and workspace agents: channels, DMs and named agents you talk to13
14// Model tiers (`ModelTier`, `MODEL_TIERS`) are integrations.ts's, the
15// same ones runs are routed between.
16import type { ModelTier } from "./integrations";
The Marketplace is where a workspace finds what to add, reached from Apps: the agent catalog of roles with who already does each job and Add to workspace; every integration with whether it's connected; g1t's own extensions, listed as Soon; and requests, where members ask and owners add or turn down, each told by a notification. Underneath, an extension is a manifest (publisher and tier, source and version from a tag, scopes, the domains its data goes to, its page on g1tusercontent.com, no price) and an install pins its version with an off switch, a budget and the audit log. Apps lists only what was added from the Marketplace, with pins; g1t's own pages stay in their sidebars, and AI Gateway joins Workspace's. The marketplace guide says how.17import type { ExtensionInstall, InstallRequest, InstallRequestStatus, InstallRequests } from "./marketplace";
Each agent has an Abilities tab: g1t's built-ins, always on within the asker's access; its computer, coming; each connected integration's actions one row each, read, import, comment or resolve, with a level for each, alone, alone when the person asked for it, ask first or never, and whose connection it runs on; and MCP servers an owner adds. Reading is alone, writing inside g1t follows today's choices, anything that leaves g1t asks first, and production deploys can't go above ask. The agents service enforces every level: ask first posts a card to allow or deny and parks a session until it's answered, a refusal names its rule in the transcript and the audit log, and a missing ability posts a request to owners. The agent abilities guide says how.18import type { AgentAbilities, AgentAbilitiesChange, McpServer } from "./abilities";
Chat and workspace agents: channels, DMs and named agents you talk to19
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)20/** The built-in orchestrator's handle; nobody else's agent may take it. */
21export const BUILTIN_AGENT_HANDLE = "g1t";
22
23/** The built-in orchestrator's template id: not one a workspace can adopt. */
24export const ORCHESTRATOR_TEMPLATE = "orchestrator";
25
Chat and workspace agents: channels, DMs and named agents you talk to26/** Voice presets; free text in `personality` refines them. */
27export type PersonalityPreset = "crisp" | "friendly" | "socratic" | "terse";
28
29export type AgentRouting = {
30 /** Never route below this tier. Null: no floor. */
31 floor: ModelTier | null;
32 /** Never route above this tier. Null: no ceiling. */
33 ceiling: ModelTier | null;
34 /**
35 * Where its model calls may go. Empty: anything the workspace allows.
36 * `g1t`: g1t's hosted models. `workspace`: the workspace's own providers
37 * (Integrations), whichever they are. Any other entry: one of the
38 * workspace's own providers by integration id. Entries combine, so
39 * `["g1t", "workspace"]` is both.
40 */
41 providers: string[];
42 /** Advanced: a fixed `provider/model`, for own endpoints. Usually null. */
43 pinned: string | null;
Pricing says it plainly: models at the provider's price, the agent rate for what g1t runs around every model call (the gateway, secrets, routing, context and pass-through to your own provider, so your own keys too), everything else at cost plus 20%, your own runners free, no seats; Security and quality comes with the plan with no separate fee, and live activations end. Each agent has an effort setting, Auto to Max, with what a typical task has cost at each level, and Spend's Spend less, keep quality suggests a lower level only when the agent's own past work shows quality held, to apply or dismiss. The pricing, spend and agents guides say how.44 /**
45 * How hard it works (docs.g1t.sh/guides/agents/#effort): the tier its
46 * work starts on, how hard the model reasons, and how many steps a
47 * session may take. `auto` (the default; absent means it) picks per
48 * piece of work. The floor and ceiling still hold.
49 */
50 effort?: AgentEffort;
Chat and workspace agents: channels, DMs and named agents you talk to51};
52
Pricing says it plainly: models at the provider's price, the agent rate for what g1t runs around every model call (the gateway, secrets, routing, context and pass-through to your own provider, so your own keys too), everything else at cost plus 20%, your own runners free, no seats; Security and quality comes with the plan with no separate fee, and live activations end. Each agent has an effort setting, Auto to Max, with what a typical task has cost at each level, and Spend's Spend less, keep quality suggests a lower level only when the agent's own past work shows quality held, to apply or dismiss. The pricing, spend and agents guides say how.53/** An agent's effort setting, cheapest first after `auto`. */
54export type AgentEffort = "auto" | "low" | "medium" | "high" | "max";
55
56export const AGENT_EFFORTS: readonly AgentEffort[] = ["auto", "low", "medium", "high", "max"];
57
58/** A level work actually ran at: what `auto` resolves to each time. */
59export type EffortLevel = Exclude<AgentEffort, "auto">;
60
61export const EFFORT_LEVELS: readonly EffortLevel[] = ["low", "medium", "high", "max"];
62
Chat and workspace agents: channels, DMs and named agents you talk to63export type AgentBudget = {
64 /** Monthly cap in micro-dollars. Null: only the workspace limit applies. */
65 monthly_micros: number | null;
66 daily_micros: number | null;
67 /** Default cap for one task. */
68 task_micros: number | null;
69};
70
71export type AgentAutonomy = {
72 open_pull_requests: "alone" | "approval";
73 merge: "alone" | "approval" | "never";
74 deploy_production: "approval" | "never";
75 edit_docs: "alone" | "suggest";
76};
77
78export type AgentStatus = "idle" | "working" | "waiting" | "out_of_budget" | "paused";
79
80export type WorkspaceAgent = {
81 id: string;
82 workspace_id: string;
83 /** Lowercase, unique in the workspace, never `g1t`. Mentioned as `@handle`. */
84 handle: string;
85 display_name: string;
86 /** Uploaded avatar hash, or null for the generated mark. */
87 avatar: string | null;
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)88 /**
89 * What its generated avatar is drawn from: a little pixel creature, the
90 * same for the same seed everywhere. Set from the handle when it is
91 * made; changing it gives the agent a new face.
92 */
93 avatar_seed: string;
94 /**
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.95 * One line, as lists show it: "QA Engineer". Its title when not written.
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)96 */
Chat and workspace agents: channels, DMs and named agents you talk to97 role: string;
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)98 /**
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.99 * Agents are hired into roles, not tasks: a title and broad
100 * responsibilities. The teams it is on are team memberships, as a
101 * person's are (identity `team_agents`), never part of the agent.
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)102 */
103 title: string;
104 /** What it is responsible for: 2 to 8 short duties, or none yet. */
105 responsibilities: string[];
106 /**
107 * Specialised help it will use inside its own work. Never members, never
108 * wider than their agent. Stored now; they run with tasks and sessions.
109 */
110 subagents: SubagentDef[];
111 /**
Agents recall what Docs say before they answer or work, and each has required reading112 * Its required reading: Docs spaces (by id) it checks first, every time
113 * it answers or works. It still reads only what the person it acts for,
114 * and everyone reading its answer, can read.
115 */
116 reading: string[];
117 /**
Every agent starts with g1t's foundational skills, playbooks for documents, research, data, code, communication, and files and media, each using only tools the agent already has and saying plainly what isn't possible yet: agents make PDFs, Word documents, spreadsheets, CSV and Markdown files with make_file, kept with a doc in Artifacts and served from g1tusercontent.com; an agent's Skills tab shows what each skill can do and with which tools, and owners turn a skill off per agent; the agent skills guide says how.118 * g1t's foundational skills turned off for it, by id (./skills.ts):
119 * every one is on unless named here. Off takes the skill's playbook out of
120 * its instructions; its tools stay as they are.
121 */
122 skills_off: string[];
123 /**
Each agent has an Abilities tab: g1t's built-ins, always on within the asker's access; its computer, coming; each connected integration's actions one row each, read, import, comment or resolve, with a level for each, alone, alone when the person asked for it, ask first or never, and whose connection it runs on; and MCP servers an owner adds. Reading is alone, writing inside g1t follows today's choices, anything that leaves g1t asks first, and production deploys can't go above ask. The agents service enforces every level: ask first posts a card to allow or deny and parks a session until it's answered, a refusal names its rule in the transcript and the audit log, and a missing ability posts a request to owners. The agent abilities guide says how.124 * What it may do (./abilities.ts, docs.g1t.sh/guides/agent-abilities/):
125 * its level and credentials for each ability it has a choice about, and
126 * the MCP servers an owner added to it. Empty means every default.
127 */
128 abilities: AgentAbilities;
129 /**
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)130 * Who it works with: `internal`, the workspace's own people (back
131 * office), or `customers` (front office). Only `internal` for now.
132 */
133 faces: AgentFaces;
Chat and workspace agents: channels, DMs and named agents you talk to134 /** The job: what it is responsible for and how it works. */
135 instructions: string;
136 personality_preset: PersonalityPreset;
137 /** Free text refining the voice. Never changes what it may do. */
138 personality: string;
139 routing: AgentRouting;
140 budget: AgentBudget;
141 autonomy: AgentAutonomy;
142 /** Tasks it works at once; more queue on its desk. */
143 capacity: number;
144 /** The template it was made from, if any. */
145 template: string | null;
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)146 /**
147 * The workspace's built-in orchestrator, `@g1t`: every workspace has one,
148 * made the first time its agents are asked for. It cannot be archived,
149 * and its handle, name, role and job are fixed; its `instructions` are
150 * added to that job. Listed first.
151 */
152 builtin: boolean;
Anyone makes an agent by describing it: one box drafts the whole agent (name, job, responsibilities, voice, skills to keep, integrations it needs, model limits and budget) as a card to change and try in a chat beside it before creating it, and an agent changes later by saying what to change, shown as a diff before it's saved. Members can make personal agents, which only they talk to and which spend from their own budget, unless owners turn that off; owners promote one to a workspace agent. The agents guide says how.153 /**
154 * Who it belongs to (docs.g1t.sh/guides/agents/, "Personal agents"):
155 * `workspace`, the workspace's own, which owners keep; or `personal`, a
156 * member's own, which only that member talks to, in their direct message
157 * with it, and whose spend counts against that member's budget.
158 */
159 scope: WorkspaceAgentScope;
160 /** For a personal agent, the member it belongs to: their user id and username. Null for a workspace agent. */
161 personal_owner_id: string | null;
162 personal_owner: string | null;
Chat and workspace agents: channels, DMs and named agents you talk to163 version: number;
164 status: AgentStatus;
165 /** Spend this calendar month, in micro-dollars. */
166 spent_month_micros: number;
167 created_by: string;
168 created_at: string;
169 updated_at: string;
170 archived_at: string | null;
171};
172
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)173/**
The docs folder is gone, and what it held lives where people read it: how a self-hosted g1t runs and how to deploy g1t to Cloudflare are pages on docs.g1t.sh under Run g1t yourself, and speed, rate limits and operating g1t.sh are sections of CONTRIBUTING.md; code that cited a file in docs/ now points to the page or section that covers it, or says what it means itself, and applied migrations and the runner images are left as they were.174 * Back office or front office (docs.g1t.sh/guides/agents/, "Back office
175 * and front office"). Customer-facing agents are not available yet.
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)176 */
177export type AgentFaces = "internal" | "customers";
178
Anyone makes an agent by describing it: one box drafts the whole agent (name, job, responsibilities, voice, skills to keep, integrations it needs, model limits and budget) as a card to change and try in a chat beside it before creating it, and an agent changes later by saying what to change, shown as a diff before it's saved. Members can make personal agents, which only they talk to and which spend from their own budget, unless owners turn that off; owners promote one to a workspace agent. The agents guide says how.179/** A workspace agent, which owners keep, or a member's personal agent. */
180export type WorkspaceAgentScope = "workspace" | "personal";
181
182/** What a personal agent starts with, unless its creator gives it other caps: $20 a month and $2 a session. */
183export const PERSONAL_AGENT_BUDGET = { monthly_micros: 20_000_000, daily_micros: null, task_micros: 2_000_000 } as const;
184
185/** Most personal agents one member keeps in a workspace. */
186export const MAX_PERSONAL_AGENTS = 10;
187
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)188/**
189 * A subagent: help an agent keeps for its own work, such as Margo's
190 * `flake-hunter`. Its routing limits sit within its agent's: a floor below
191 * the agent's is raised to it, a ceiling above is lowered to it.
192 */
193export type SubagentDef = {
194 /** Lowercase letters, digits and hyphens: `flake-hunter`. Unique on the agent. */
195 name: string;
196 /** One line: what it is for. */
197 description: string;
198 instructions: string;
199 routing: { floor: ModelTier | null; ceiling: ModelTier | null };
200 /** How many of it may run at once inside one task, 1 to 8. */
201 max_parallel: number;
202};
203
Chat and workspace agents: channels, DMs and named agents you talk to204export type NewWorkspaceAgent = {
205 handle: string;
206 display_name: string;
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.207 /** Left out or empty: its title. */
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)208 role?: string;
209 title?: string;
210 responsibilities?: string[];
211 subagents?: SubagentDef[];
Agents recall what Docs say before they answer or work, and each has required reading212 /** Docs spaces (by id) it reads first; at most 10. */
213 reading?: string[];
Every agent starts with g1t's foundational skills, playbooks for documents, research, data, code, communication, and files and media, each using only tools the agent already has and saying plainly what isn't possible yet: agents make PDFs, Word documents, spreadsheets, CSV and Markdown files with make_file, kept with a doc in Artifacts and served from g1tusercontent.com; an agent's Skills tab shows what each skill can do and with which tools, and owners turn a skill off per agent; the agent skills guide says how.214 /** Foundational skills to turn off, by id (./skills.ts). */
215 skills_off?: string[];
Each agent has an Abilities tab: g1t's built-ins, always on within the asker's access; its computer, coming; each connected integration's actions one row each, read, import, comment or resolve, with a level for each, alone, alone when the person asked for it, ask first or never, and whose connection it runs on; and MCP servers an owner adds. Reading is alone, writing inside g1t follows today's choices, anything that leaves g1t asks first, and production deploys can't go above ask. The agents service enforces every level: ask first posts a card to allow or deny and parks a session until it's answered, a refusal names its rule in the transcript and the audit log, and a missing ability posts a request to owners. The agent abilities guide says how.216 /**
217 * Its abilities' levels and credentials (./abilities.ts), whole: what is
218 * sent replaces what it had. MCP servers are added and removed with
219 * `addMcpServer` and `removeMcpServer`, never here.
220 */
221 abilities?: AgentAbilitiesChange;
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)222 /** Only `internal` for now; `customers` is refused. */
223 faces?: AgentFaces;
Chat and workspace agents: channels, DMs and named agents you talk to224 instructions: string;
225 personality_preset?: PersonalityPreset;
226 personality?: string;
227 routing?: Partial<AgentRouting>;
228 budget?: Partial<AgentBudget>;
229 autonomy?: Partial<AgentAutonomy>;
230 capacity?: number;
231 template?: string | null;
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)232 /** Its avatar's seed; left out, the handle. */
233 avatar_seed?: string;
Anyone makes an agent by describing it: one box drafts the whole agent (name, job, responsibilities, voice, skills to keep, integrations it needs, model limits and budget) as a card to change and try in a chat beside it before creating it, and an agent changes later by saying what to change, shown as a diff before it's saved. Members can make personal agents, which only they talk to and which spend from their own budget, unless owners turn that off; owners promote one to a workspace agent. The agents guide says how.234 /**
235 * When creating: `workspace` (owners only, and their default) or
236 * `personal` (any member, when the workspace lets members make them; a
237 * member's default). Ignored on a change: an owner promotes instead.
238 */
239 scope?: WorkspaceAgentScope;
Chat and workspace agents: channels, DMs and named agents you talk to240};
241
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)242/**
Anyone makes an agent by describing it: one box drafts the whole agent (name, job, responsibilities, voice, skills to keep, integrations it needs, model limits and budget) as a card to change and try in a chat beside it before creating it, and an agent changes later by saying what to change, shown as a diff before it's saved. Members can make personal agents, which only they talk to and which spend from their own budget, unless owners turn that off; owners promote one to a workspace agent. The agents guide says how.243 * What g1t drafted from a description (docs.g1t.sh/guides/agents/,
244 * "Describe it"): a whole definition to edit before anything is saved,
245 * and what the agent will want around it. Nothing here is saved until the
246 * agent is created.
247 */
248export type AgentProposal = {
249 /** A complete definition, ready to create as it is. */
250 definition: NewWorkspaceAgent & { scope: WorkspaceAgentScope };
251 /** Other names that suit it, for the shuffle. */
252 name_ideas: string[];
253 /** Foundational skills it should keep on, by id (./skills.ts); the rest are off in `definition.skills_off`. */
254 skills: string[];
255 /** Integrations the job needs, from the catalog (./connectors.ts), with why. */
256 integrations: { id: string; why: string }[];
257 /** Routines that would suit it, to set up on its Routines tab once it exists. */
258 routines: { name: string; when: string; instructions: string }[];
259 /** What drafting it cost, charged to the person who asked (micro-dollars). */
260 charged_micros: number;
261};
262
263/** One line of a Try it conversation, held by the page, never saved. */
264export type DraftTurn = { role: "user" | "assistant"; content: string };
265
266/** A Try it answer, and what it cost the person trying it. */
267export type DraftReply = { text: string; charged_micros: number };
268
269/** Changes drafted from "Tell <name> what to change", to review before they are saved as a new version. */
270export type AgentRedraft = {
271 /** The changes to save, as `update` takes them: only fields that differ. */
272 changes: Partial<NewWorkspaceAgent>;
273 /** One line on what changed. */
274 summary: string;
275 /** The version it was drafted from. */
276 from_version: number;
277 charged_micros: number;
278};
279
280/**
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.281 * A role to hire an agent into, by title. Agents get names, not job
282 * titles ("Margo", the QA Engineer). A template never puts an agent on a
283 * team.
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)284 */
Chat and workspace agents: channels, DMs and named agents you talk to285export type AgentTemplate = {
286 id: string;
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)287 /** The name it suggests first. */
Chat and workspace agents: channels, DMs and named agents you talk to288 display_name: string;
289 handle: string;
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)290 /** Other names that suit it, for the form's shuffle. Each is also a valid handle, lowercased. */
291 name_ideas: string[];
Chat and workspace agents: channels, DMs and named agents you talk to292 role: string;
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)293 title: string;
294 responsibilities: string[];
295 subagents: SubagentDef[];
Chat and workspace agents: channels, DMs and named agents you talk to296 instructions: string;
297 personality_preset: PersonalityPreset;
298 routing: AgentRouting;
299};
300
301/** What the chat service hands an agent: a message it should answer. */
302export type AgentDelivery = {
303 workspace: string;
304 workspace_id: string;
305 channel_id: string;
306 channel_kind: "channel" | "dm";
307 channel_name: string | null;
308 agent_id: string;
309 /** The message that woke it. */
310 message_id: string;
311 thread_root: string | null;
312 /** Who asked: the person's user id. */
313 asked_by: string;
314 /** Agent-to-agent hops so far in this chain. */
315 hops: number;
316 /**
317 * What the person who asked may do, from the viewer the chat service
318 * already holds when the message is posted (`askerAccess`). An agent
The docs folder is gone, and what it held lives where people read it: how a self-hosted g1t runs and how to deploy g1t to Cloudflare are pages on docs.g1t.sh under Run g1t yourself, and speed, rate limits and operating g1t.sh are sections of CONTRIBUTING.md; code that cited a file in docs/ now points to the page or section that covers it, or says what it means itself, and applied migrations and the runner images are left as they were.319 * never does more for someone than they could do themselves. Absent
320 * from an older chat service: the agent then treats the asker as unable
321 * to change code.
Chat and workspace agents: channels, DMs and named agents you talk to322 */
323 asker?: AskerAccess | null;
324 /**
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)325 * The agents that handled this request before this one, by id, oldest
326 * first; the last sent the work here. An agent never hands back or
327 * consults the one that sent it work, and the hop limit counts every
328 * hand-off and consult along the chain. Absent: none (a person asked).
329 */
330 chain?: string[];
331 /**
Chat and workspace agents: channels, DMs and named agents you talk to332 * Where the conversation is: g1t's own chat, or later another chat app
The docs folder is gone, and what it held lives where people read it: how a self-hosted g1t runs and how to deploy g1t to Cloudflare are pages on docs.g1t.sh under Run g1t yourself, and speed, rate limits and operating g1t.sh are sections of CONTRIBUTING.md; code that cited a file in docs/ now points to the page or section that covers it, or says what it means itself, and applied migrations and the runner images are left as they were.333 * the workspace connected. The agent reads and replies through that
334 * surface; its definition, budget and replies are the same everywhere.
335 * Absent: `g1t`.
Chat and workspace agents: channels, DMs and named agents you talk to336 */
337 surface?: AgentSurface;
338};
339
340/** The chat surfaces an agent answers on. Only g1t's own today. */
341export type AgentSurface = "g1t";
342
343/** Who asked an agent, as far as its reply needs to know. */
344export type AskerAccess = {
345 username: string;
346 /** Their role in the workspace; `outside` for someone who is not a member. */
347 role: Role | "outside";
348 /**
349 * Whether they can change code in the workspace: Code is on for them
350 * and they hold write access (or more) on at least one of its
351 * repositories, through the base permission or a grant.
352 */
353 can_write: boolean;
354};
355
356const WRITING_ROLES = new Set(["write", "maintain", "admin"]);
357
358/**
359 * `user`'s access in `workspace`, for `AgentDelivery.asker`. Pure, with no
360 * imports, so the chat service computes it from its viewer for free.
361 */
362export function askerAccess(user: User, workspace: string): AskerAccess {
363 const slug = workspace.toLowerCase();
364 const membership = user.workspaces?.find((m) => m.slug.toLowerCase() === slug);
365 // Someone who uses only Chat, Docs and agents sees no repository at all.
366 const code = membership?.code_access !== false;
367 const base = membership ? membership.role === "owner" || WRITING_ROLES.has(membership.base_permission ?? "write") : false;
368 const granted = (user.grants ?? []).some((grant) => grant.workspace.toLowerCase() === slug && WRITING_ROLES.has(grant.role));
369 return {
370 username: user.username,
371 role: membership?.role ?? "outside",
372 can_write: code && (base || granted),
373 };
374}
375
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked376/**
The docs folder is gone, and what it held lives where people read it: how a self-hosted g1t runs and how to deploy g1t to Cloudflare are pages on docs.g1t.sh under Run g1t yourself, and speed, rate limits and operating g1t.sh are sections of CONTRIBUTING.md; code that cited a file in docs/ now points to the page or section that covers it, or says what it means itself, and applied migrations and the runner images are left as they were.377 * A session: one bounded piece of work an agent took on
378 * (docs.g1t.sh/guides/agent-sessions/). A conversation with an agent is
379 * not a session: talking stays cheap and quick, and when a request needs
380 * real work the agent spins off a session for it, with its own context, transcript, budget and live card in
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked381 * the conversation. Sessions start other sessions (one of the agent's
382 * subagents, or a colleague brought in), and everything a tree of sessions
383 * spends is charged to the agent at its root, so a chain never escapes the
384 * budget that started it.
385 */
386export type AgentSessionKind =
387 /** Spun off from a conversation: someone asked for work. */
388 | "chat"
389 /** A routine's run. */
390 | "routine"
391 /** A colleague brought in by another session. */
392 | "helper"
393 /** One of the agent's own subagents, inside another session. */
394 | "subagent";
395
396export type AgentSessionStatus =
397 | "queued"
398 | "working"
399 /** Waiting on sessions it started. */
400 | "waiting"
401 /** Stopped at its spend cap: someone who may raise it decides. */
402 | "needs_approval"
403 | "done"
404 | "failed"
405 | "stopped";
406
407/** The statuses of a session that is not over. */
408export const SESSION_LIVE: readonly AgentSessionStatus[] = ["queued", "working", "waiting", "needs_approval"];
409
410export type AgentSession = {
411 id: string;
412 workspace_id: string;
413 agent_id: string;
414 /** The agent's handle, name and face, for lists. */
415 agent_handle: string;
416 agent_name: string;
417 agent_avatar_seed: string;
418 /** The subagent running it, by name, when kind is `subagent`. */
419 subagent: string | null;
420 kind: AgentSessionKind;
421 /** The session that started it, and the root of its tree. */
422 parent_id: string | null;
423 root_id: string;
424 /** Whose budget pays for it: the agent at the root of its tree. */
425 payer_agent_id: string;
426 title: string;
427 goal: string;
428 status: AgentSessionStatus;
429 /** Why it is waiting, stopped or failed, in a line. */
430 status_note: string | null;
431 /** What it found or did, once done: its report. */
432 summary: string | null;
433 /** Where it reports: the conversation it was started from. */
434 channel_id: string;
435 channel_kind: "channel" | "dm";
436 channel_name: string | null;
437 /** Its live card in that conversation; its updates go in the card's thread. */
438 card_message_id: string | null;
439 asked_by: string | null;
440 asked_by_username: string | null;
441 routine_id: string | null;
442 steps: number;
443 tool_calls: number;
444 input_tokens: number;
445 output_tokens: number;
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.446 /**
447 * At list price, what it counts against budgets: the model at the
448 * provider's price with billing's model margin, plus g1t's agent rate on
449 * every token. A root session's includes everything its tree spent.
450 */
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked451 charged_micros: number;
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.452 /** What its own steps' model answers cost at the provider's price, its tree's not included. */
453 cost_micros: number;
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked454 /** The most it may spend before someone approves more. */
455 cap_micros: number | null;
456 model: string | null;
Pricing says it plainly: models at the provider's price, the agent rate for what g1t runs around every model call (the gateway, secrets, routing, context and pass-through to your own provider, so your own keys too), everything else at cost plus 20%, your own runners free, no seats; Security and quality comes with the plan with no separate fee, and live activations end. Each agent has an effort setting, Auto to Max, with what a typical task has cost at each level, and Spend's Spend less, keep quality suggests a lower level only when the agent's own past work shows quality held, to apply or dismiss. The pricing, spend and agents guides say how.457 /** The effort level it ran at (the highest, when `auto` raised it); null for sessions from before effort was recorded. */
458 effort: EffortLevel | null;
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked459 /** What it produced: issues filed, sessions started. */
460 outputs: SessionOutput[];
461 created_at: string;
462 updated_at: string;
463 finished_at: string | null;
464 /**
465 * False when the viewer is not among the people of the conversation it
466 * came from: they see that it ran and what it cost, never its title,
467 * goal, report or transcript.
468 */
469 visible: boolean;
470};
471
472export type SessionOutput =
473 | { kind: "issue"; repo: string; number: number; title: string }
474 | { kind: "session"; id: string; agent_handle: string; title: string }
475 | { kind: "memory"; id: string; body: string };
476
477/** One entry of a session's transcript, as its page shows it. */
478export type SessionEvent = {
479 seq: number;
480 kind: "goal" | "text" | "tool" | "steer" | "update" | "child" | "result" | "note";
481 /** Who: the agent's handle, a person's username (steering), or null for g1t's notes. */
482 by: string | null;
483 body: string;
484 /** For `tool`: the tool, and whether it read, was withheld, refused or failed. */
485 tool: string | null;
486 outcome: string | null;
487 created_at: string;
488};
489
490export type AgentSessionDetail = {
491 session: AgentSession;
492 events: SessionEvent[];
493 /** Every session in its tree, root first. */
494 tree: AgentSession[];
495 /** Whether the viewer may stop it, steer it, or approve more spend. */
496 can_stop: boolean;
497 can_steer: boolean;
498 can_approve: boolean;
499};
500
501/**
The docs folder is gone, and what it held lives where people read it: how a self-hosted g1t runs and how to deploy g1t to Cloudflare are pages on docs.g1t.sh under Run g1t yourself, and speed, rate limits and operating g1t.sh are sections of CONTRIBUTING.md; code that cited a file in docs/ now points to the page or section that covers it, or says what it means itself, and applied migrations and the runner images are left as they were.502 * What an agent remembers (docs.g1t.sh/guides/agent-memory/). Every fact
503 * carries where it came from, and its scope decides, in code, where it may
504 * be recalled and who may see it:
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked505 *
506 * - `workspace`: anywhere in the workspace. Owners write these, or an agent
507 * from a public channel, which every member can read already.
508 * - `channel`: only in that channel and its threads.
509 * - `person`: only in a direct message with that one person.
510 */
511export type AgentMemoryScope = "workspace" | "channel" | "person";
512
513export type AgentMemory = {
514 id: string;
515 agent_id: string;
516 scope: AgentMemoryScope;
517 /** The channel's id or the person's user id; empty for `workspace`. */
518 scope_ref: string;
519 /** The channel's name or the person's username, for display. */
520 scope_label: string | null;
521 body: string;
522 source_kind: "message" | "session" | "person";
523 /** A message id, a session id, or the username of who wrote it. */
524 source_ref: string | null;
525 source_label: string | null;
526 /** The channel the source is in, for a link. */
527 source_channel_id: string | null;
528 created_by: string;
529 created_by_kind: "agent" | "user";
530 pinned: boolean;
531 created_at: string;
532 updated_at: string;
533};
534
535/** When a routine runs, in UTC. */
536export type RoutineSchedule = {
537 every: "hour" | "day" | "weekday" | "week";
538 /** Minute of the hour, 0 to 59. */
539 minute: number;
540 /** Hour of the day (UTC), 0 to 23; not used for `hour`. */
541 hour: number;
542 /** Day of the week for `week`, 0 (Sunday) to 6. */
543 weekday: number;
544};
545
546/**
Routines run when something happens: a pull request ready for review or merged, checks or a deploy failing, an issue opened547 * Things that happen in the workspace a routine can run on
The docs folder is gone, and what it held lives where people read it: how a self-hosted g1t runs and how to deploy g1t to Cloudflare are pages on docs.g1t.sh under Run g1t yourself, and speed, rate limits and operating g1t.sh are sections of CONTRIBUTING.md; code that cited a file in docs/ now points to the page or section that covers it, or says what it means itself, and applied migrations and the runner images are left as they were.548 * (docs.g1t.sh/guides/agent-routines/). Each run is one session about the one
Routines run when something happens: a pull request ready for review or merged, checks or a deploy failing, an issue opened549 * thing that happened, in a repository its sponsor can read.
550 */
551export const ROUTINE_EVENTS = [
552 { key: "pull_ready", label: "A pull request is ready for review", hint: "Opened ready, or moved out of draft." },
553 { key: "pull_merged", label: "A pull request is merged", hint: "On any branch it targets." },
554 { key: "checks_failed", label: "Checks fail on a pull request", hint: "Its required checks failed or errored." },
555 { key: "issue_opened", label: "An issue is opened", hint: "By a person or an agent." },
556 { key: "deploy_failed", label: "A deploy fails", hint: "A production or preview deploy." },
557] as const;
558
559export type RoutineEvent = (typeof ROUTINE_EVENTS)[number]["key"];
560
561/**
Merge branch 'chat-sidebar' into fast-push562 * A routine: work an agent does on a schedule or when something happens, such as Sam's Monday digest
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked563 * of support themes. Each run is a session posted in the routine's channel,
564 * paid from the agent's budget, and run with the access of the person who
565 * set it up (its sponsor), never more.
566 */
567export type AgentRoutine = {
568 id: string;
569 agent_id: string;
570 name: string;
571 instructions: string;
Routines run when something happens: a pull request ready for review or merged, checks or a deploy failing, an issue opened572 /** When it runs on a clock; null when it runs only on events. */
573 schedule: RoutineSchedule | null;
574 /** What it runs on; empty when it runs only on its schedule. */
575 events: RoutineEvent[];
576 /** Which repositories its events come from, by `workspace/name`; empty: every one its sponsor can read. */
577 repos: string[];
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked578 channel_id: string;
579 channel_name: string | null;
580 sponsor: string;
581 sponsor_username: string | null;
582 enabled: boolean;
583 /** Why g1t paused it, when it did. */
584 paused_note: string | null;
585 next_run_at: string | null;
586 last_run_at: string | null;
587 last_session_id: string | null;
588 runs: number;
589 created_at: string;
590 updated_at: string;
591};
592
Routines run when something happens: a pull request ready for review or merged, checks or a deploy failing, an issue opened593/** A routine suggested from an agent's responsibilities, for an owner to add in one step. */
594export type RoutineSuggestion = { responsibility: string; routine: Omit<NewRoutine, "channel_id"> };
595
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked596export type NewRoutine = {
597 name: string;
598 instructions: string;
Routines run when something happens: a pull request ready for review or merged, checks or a deploy failing, an issue opened599 /** A schedule, events, or both; at least one. */
600 schedule: RoutineSchedule | null;
601 events?: RoutineEvent[];
602 repos?: string[];
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked603 /** A channel the agent is in, by id. */
604 channel_id: string;
605 enabled?: boolean;
606};
607
608/**
609 * The workspace's say over all its agents together, set by owners: one
610 * monthly budget across every agent, the budget a new agent starts with,
611 * and the cap a session starts with. The workspace's spend limit and AI
612 * credit (billing) sit above all of it.
613 */
614export type AgentPolicy = {
615 /** Every agent's spend together in a month. Null: only the workspace's spend limit. */
616 monthly_micros: number | null;
617 /** The monthly budget a new agent gets. Null: none. */
618 default_agent_monthly_micros: number | null;
619 /** The cap one session starts with, unless its agent's per-task cap is lower. */
620 default_session_micros: number;
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.621 /**
622 * What the agents working for one person (their replies and sessions,
623 * asked for by that person) may spend together in a month, unless the
624 * person has a budget of their own. Null: no budget per person.
625 */
626 person_monthly_micros: number | null;
Anyone makes an agent by describing it: one box drafts the whole agent (name, job, responsibilities, voice, skills to keep, integrations it needs, model limits and budget) as a card to change and try in a chat beside it before creating it, and an agent changes later by saying what to change, shown as a diff before it's saved. Members can make personal agents, which only they talk to and which spend from their own budget, unless owners turn that off; owners promote one to a workspace agent. The agents guide says how.627 /**
628 * Whether members who aren't owners may create personal agents
629 * (docs.g1t.sh/guides/agents/, "Personal agents"). On unless an owner
630 * turns it off; off, existing personal agents keep working.
631 */
632 members_create_agents: boolean;
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.633};
634
635/** One person's budget: what agents working for them may spend in a month, and what they have. */
636export type PersonBudget = {
637 username: string;
638 /** The budget that applies: their own, or the workspace's per-person default. Null: none. */
639 monthly_micros: number | null;
640 /** Whether it is their own, set by an owner, rather than the default. */
641 own: boolean;
642 /** What agents spent for them this month (UTC). */
643 spent_micros: number;
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked644};
645
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.646/** Budgets per person: the default, and each person who has one of their own or has spent this month. */
647export type PersonBudgets = {
648 period: string;
649 default_micros: number | null;
650 /** Owners see everyone; anyone else sees only themselves. Most spent first. */
651 people: PersonBudget[];
652};
653
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked654export type SpendSlice = { key: string; label: string; micros: number; count: number };
655
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.656/** Which days a breakdown covers: this month (the default), last month, or the last 7 or 30 days, in UTC. */
657export type SpendPeriod = "month" | "last_month" | "7d" | "30d";
658
659/** Where an agent's (or every agent's) spend went over a period. */
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked660export type AgentSpendBreakdown = {
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.661 /** `YYYY-MM` for a month; for a span of days, the month it ends in. */
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked662 period: string;
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.663 /** The span asked for, and its first and last day (`YYYY-MM-DD`, both included). */
664 span: SpendPeriod;
665 from: string;
666 until: string;
667 /** The one person it is about (work asked for by them), or null for everyone's. */
668 person: string | null;
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked669 total_micros: number;
670 /** Chat replies, sessions, routines, helping colleagues. */
671 by_kind: SpendSlice[];
672 by_model: SpendSlice[];
673 /** Who asked: the work done for each person. */
674 by_person: SpendSlice[];
675 by_agent: SpendSlice[];
676 by_team: SpendSlice[];
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.677 /**
678 * Where it was asked: a channel by id (labelled `#name`), direct
679 * messages together (`dm`), and channels the viewer can't read together
680 * (`private`).
681 */
682 by_channel: SpendSlice[];
683 /** The costliest sessions in the period. */
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked684 top_sessions: AgentSession[];
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.685 /** Spend by day in the period. */
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked686 days: { day: string; micros: number }[];
687};
688
Pricing says it plainly: models at the provider's price, the agent rate for what g1t runs around every model call (the gateway, secrets, routing, context and pass-through to your own provider, so your own keys too), everything else at cost plus 20%, your own runners free, no seats; Security and quality comes with the plan with no separate fee, and live activations end. Each agent has an effort setting, Auto to Max, with what a typical task has cost at each level, and Spend's Spend less, keep quality suggests a lower level only when the agent's own past work shows quality held, to apply or dismiss. The pricing, spend and agents guides say how.689/**
690 * What each effort level has cost one agent, from its own finished
691 * sessions (docs.g1t.sh/guides/spend/#effort): measured, never estimated
692 * from other agents or list prices. A level it has not run at has no
693 * figures.
694 */
695export type EffortCost = {
696 effort: EffortLevel;
697 /** Its sessions (with everything they brought in) that finished in the window. */
698 sessions: number;
699 /** The median charged for one of them: a typical task. Null with none. */
700 typical_micros: number | null;
701 /** Of those, the share finished with nobody having to step in: no steering, not stopped or failed. Null with none. */
702 accepted_share: number | null;
703};
704
705export type AgentEffortCosts = {
706 handle: string;
707 /** Its setting now. */
708 effort: AgentEffort;
709 /** Days of history the figures cover. */
710 window_days: number;
711 levels: EffortCost[];
712};
713
714/** One side of a recommendation's evidence: the agent's sessions at one level. */
715export type EffortEvidence = {
716 effort: EffortLevel;
717 sessions: number;
718 /** Finished with nobody having to step in. */
719 accepted: number;
720 typical_micros: number;
721 mean_micros: number;
722};
723
724/**
725 * A way to spend less without losing quality, checked against the agent's
726 * own past work (docs.g1t.sh/guides/spend/#spend-less-keep-quality). The
727 * weekly check proposes one only when the cheaper level's measured
728 * outcomes hold up; when there is too little history to tell, it says so
729 * (`thin`) instead of proposing anything.
730 */
731export type AgentRecommendation = {
732 id: string;
733 agent_id: string;
734 agent_handle: string;
735 agent_name: string;
736 agent_avatar_seed: string;
737 /** Lowering its effort setting. */
738 kind: "effort";
739 /** `thin`: not enough history to recommend anything yet. */
740 status: "open" | "applied" | "dismissed" | "thin";
741 from_effort: AgentEffort;
742 to_effort: EffortLevel;
743 /** What it says to do, in a line. */
744 title: string;
745 /** Why, from the numbers in `evidence`, in a sentence. */
746 reason: string;
747 /** What it was measured on: the level it runs at now, and the cheaper one. Null sides had no sessions. */
748 evidence: { window_days: number; current: EffortEvidence | null; cheaper: EffortEvidence | null; needed: number };
749 /** About what a month it would save at the recent pace, from the measured costs. Null when thin. */
750 saving_month_micros: number | null;
751 checked_at: string;
752 resolved_by: string | null;
753 resolved_at: string | null;
754};
755
756export type AgentRecommendations = {
757 /** When the check last ran for the workspace; null before the first. */
758 checked_at: string | null;
759 window_days: number;
760 /** To act on, largest saving first. */
761 open: AgentRecommendation[];
762 /** Agents with too little history to say. */
763 thin: AgentRecommendation[];
764 /** Applied or dismissed in the last 30 days. */
765 resolved: AgentRecommendation[];
766};
767
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked768/** Agents mode's front page. */
769export type AgentsOverview = {
770 policy: AgentPolicy;
771 /** Every agent's spend this month, against the policy's budget. */
772 spent_month_micros: number;
773 /** The highest alert this month: 75, 90 or 100 (% of the workspace's agent budget). */
774 alert: number | null;
775 agents: WorkspaceAgent[];
776 /** Live sessions, counted by agent id, for the roster. */
777 live_by_agent: Record<string, number>;
778 /** Sessions live now that the viewer can see. */
779 live: AgentSession[];
780 /** Sessions waiting on the viewer: spend they may approve. */
781 waiting_on_you: AgentSession[];
782 /** Recently finished sessions the viewer can see. */
783 recent: AgentSession[];
Routines run when something happens: a pull request ready for review or merged, checks or a deploy failing, an issue opened784 /** The next routines to run on a schedule. */
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked785 upcoming: (AgentRoutine & { agent_handle: string; agent_name: string })[];
786 spend: AgentSpendBreakdown;
787 can_manage: boolean;
788};
789
790/** One thing an agent did, for its Activity tab. */
791export type AgentActivity = {
792 id: string;
793 kind: "reply" | "session";
794 status: string;
795 channel_id: string;
796 channel_name: string | null;
797 /** The session's title; null for a reply or one the viewer can't see. */
798 title: string | null;
799 asked_by_username: string | null;
800 model: string | null;
801 tools: number;
802 charged_micros: number;
803 created_at: string;
804 visible: boolean;
805 /** For a reply, the message it posted; for a session, its id. */
806 ref: string | null;
807};
808
809export type AgentVersion = { version: number; changed_by: string; created_at: string; definition: Partial<NewWorkspaceAgent> };
810
Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar811/** A card action, as chat hands it to agents. */
812export type AgentCardAction = {
813 workspace: string;
814 channel_id: string;
815 message_id: string;
816 viewer: User;
817 card: { kind: string; ref: string | null };
818 action_id: string;
819 input: string | null;
820};
821
Chat and workspace agents: channels, DMs and named agents you talk to822export type WorkspaceAgentsApi = {
Anyone makes an agent by describing it: one box drafts the whole agent (name, job, responsibilities, voice, skills to keep, integrations it needs, model limits and budget) as a card to change and try in a chat beside it before creating it, and an agent changes later by saying what to change, shown as a diff before it's saved. Members can make personal agents, which only they talk to and which spend from their own budget, unless owners turn that off; owners promote one to a workspace agent. The agents guide says how.823 /**
824 * The workspace's agents. Personal agents are left out unless asked
825 * for: `mine`, the viewer's own; `all`, every member's for an owner (the
826 * viewer's own for anyone else).
827 */
828 list(workspace: string, viewer: User, options?: { personal?: "mine" | "all" | null }): Promise<Result<WorkspaceAgent[]>>;
Chat and workspace agents: channels, DMs and named agents you talk to829 get(workspace: string, handle: string, viewer: User): Promise<Result<WorkspaceAgent>>;
830 /** Internal: by id, for the chat service resolving members. */
831 byIds(ids: string[]): Promise<WorkspaceAgent[]>;
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.832 /**
833 * `teams`: the workspace's teams to add it to as it is made, by slug,
834 * each one the viewer manages (owners and the team's maintainers). The
835 * membership is the team's, as anyone's is; a personal agent joins none.
836 */
837 create(workspace: string, viewer: User, input: NewWorkspaceAgent, options?: { teams?: string[] }): Promise<Result<WorkspaceAgent>>;
Chat and workspace agents: channels, DMs and named agents you talk to838 update(
839 workspace: string,
840 handle: string,
841 viewer: User,
842 changes: Partial<NewWorkspaceAgent>,
843 ): Promise<Result<WorkspaceAgent>>;
844 archive(workspace: string, handle: string, viewer: User): Promise<Result<null>>;
Anyone makes an agent by describing it: one box drafts the whole agent (name, job, responsibilities, voice, skills to keep, integrations it needs, model limits and budget) as a card to change and try in a chat beside it before creating it, and an agent changes later by saying what to change, shown as a diff before it's saved. Members can make personal agents, which only they talk to and which spend from their own budget, unless owners turn that off; owners promote one to a workspace agent. The agents guide says how.845 /**
846 * Drafts a whole agent from a description, with a fast model call charged
847 * to the viewer. Nothing is saved. Whoever may create the agent may draft it.
848 */
849 draft(workspace: string, viewer: User, input: { description: string; scope?: WorkspaceAgentScope | null }): Promise<Result<AgentProposal>>;
850 /**
851 * Try it: the unsaved definition answers the conversation so far, as it
852 * would in a direct message, without tools or memory. Charged to the
853 * viewer; nothing is saved.
854 */
855 tryDraft(workspace: string, viewer: User, input: { definition: NewWorkspaceAgent; messages: DraftTurn[] }): Promise<Result<DraftReply>>;
856 /** Drafts changes to an agent from a request in words; saved only through `update`. Whoever may change the agent may ask. */
857 redraft(workspace: string, handle: string, viewer: User, request: string): Promise<Result<AgentRedraft>>;
858 /**
859 * Owners make a member's personal agent a workspace agent: its definition
860 * and every version move to a workspace agent with the same handle, and
861 * the personal one is archived, with its memory and direct messages.
862 */
863 promote(workspace: string, handle: string, viewer: User): Promise<Result<WorkspaceAgent>>;
Each agent has an Abilities tab: g1t's built-ins, always on within the asker's access; its computer, coming; each connected integration's actions one row each, read, import, comment or resolve, with a level for each, alone, alone when the person asked for it, ask first or never, and whose connection it runs on; and MCP servers an owner adds. Reading is alone, writing inside g1t follows today's choices, anything that leaves g1t asks first, and production deploys can't go above ask. The agents service enforces every level: ask first posts a card to allow or deny and parks a session until it's answered, a refusal names its rule in the transcript and the audit log, and a missing ability posts a request to owners. The agent abilities guide says how.864 /**
865 * Adds an MCP server to an agent (docs.g1t.sh/guides/agent-abilities/,
866 * "MCP servers"): its host is checked, its tools are listed from it, and
867 * the agent gets a new version with each tool as an ability. Owners only.
868 */
869 addMcpServer(workspace: string, handle: string, viewer: User, input: { name: string; url: string }): Promise<Result<McpServer>>;
870 /** Takes an MCP server off an agent, with its abilities: a new version. Owners only. */
871 removeMcpServer(workspace: string, handle: string, viewer: User, id: string): Promise<Result<null>>;
872 /** Lists a server's tools again, for one that changed; a new version when they did. Owners only. */
873 refreshMcpServer(workspace: string, handle: string, viewer: User, id: string): Promise<Result<McpServer>>;
Chat and workspace agents: channels, DMs and named agents you talk to874 templates(): Promise<AgentTemplate[]>;
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)875 /**
876 * Internal: the workspace's built-in `@g1t` agent, made if it does not
877 * exist yet. The chat service asks for it when someone mentions @g1t in
878 * a channel it is not in yet.
879 */
880 builtin(workspace: string, workspaceId: string): Promise<Result<WorkspaceAgent>>;
Chat and workspace agents: channels, DMs and named agents you talk to881 /** The chat service hands over a message for an agent to answer. Returns at once. */
882 deliver(delivery: AgentDelivery): Promise<Result<null>>;
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked883 overview(workspace: string, viewer: User): Promise<Result<AgentsOverview>>;
884 sessions(
885 workspace: string,
886 viewer: User,
887 filter?: { handle?: string | null; status?: "live" | "done" | null; limit?: number | null },
888 ): Promise<Result<AgentSession[]>>;
889 session(workspace: string, id: string, viewer: User): Promise<Result<AgentSessionDetail>>;
890 /** Stops a session and every session under it. */
891 stopSession(workspace: string, id: string, viewer: User): Promise<Result<AgentSession>>;
892 /** Raises a stopped session's cap and lets it go on. Owners only. */
893 approveSession(workspace: string, id: string, viewer: User, capMicros: number): Promise<Result<AgentSession>>;
894 /** A person's message to a session, running or finished: it reads it and goes on. */
895 steerSession(workspace: string, id: string, viewer: User, body: string): Promise<Result<AgentSession>>;
896 memories(workspace: string, handle: string, viewer: User): Promise<Result<AgentMemory[]>>;
897 remember(
898 workspace: string,
899 handle: string,
900 viewer: User,
901 input: { body: string; scope: AgentMemoryScope; scope_ref?: string | null },
902 ): Promise<Result<AgentMemory>>;
903 updateMemory(
904 workspace: string,
905 handle: string,
906 viewer: User,
907 id: string,
908 changes: { body?: string; pinned?: boolean },
909 ): Promise<Result<AgentMemory>>;
910 forget(workspace: string, handle: string, viewer: User, id: string): Promise<Result<null>>;
Routines run when something happens: a pull request ready for review or merged, checks or a deploy failing, an issue opened911 routines(workspace: string, handle: string, viewer: User): Promise<Result<{ routines: AgentRoutine[]; suggestions: RoutineSuggestion[] }>>;
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked912 saveRoutine(workspace: string, handle: string, viewer: User, input: NewRoutine, id?: string | null): Promise<Result<AgentRoutine>>;
913 deleteRoutine(workspace: string, handle: string, viewer: User, id: string): Promise<Result<null>>;
914 /** Runs a routine now, as a session. */
915 runRoutine(workspace: string, handle: string, viewer: User, id: string): Promise<Result<AgentSession>>;
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.916 /**
917 * Where the spend went: one agent's, or every agent's; this month unless
918 * `period` says otherwise; for everyone, or only the work one `person`
919 * (by username) asked for.
920 */
921 spend(workspace: string, viewer: User, handle?: string | null, options?: { period?: SpendPeriod | null; person?: string | null }): Promise<Result<AgentSpendBreakdown>>;
922 /** Budgets per person this month: owners see everyone's, anyone else their own. */
923 personBudgets(workspace: string, viewer: User): Promise<Result<PersonBudgets>>;
924 /**
925 * Gives one person a monthly budget of their own (`monthly_micros`; 0 for
926 * no budget at all), or with null puts them back on the default. Owners only.
927 */
928 setPersonBudget(workspace: string, viewer: User, username: string, monthlyMicros: number | null): Promise<Result<PersonBudgets>>;
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked929 activity(workspace: string, handle: string, viewer: User): Promise<Result<AgentActivity[]>>;
Pricing says it plainly: models at the provider's price, the agent rate for what g1t runs around every model call (the gateway, secrets, routing, context and pass-through to your own provider, so your own keys too), everything else at cost plus 20%, your own runners free, no seats; Security and quality comes with the plan with no separate fee, and live activations end. Each agent has an effort setting, Auto to Max, with what a typical task has cost at each level, and Spend's Spend less, keep quality suggests a lower level only when the agent's own past work shows quality held, to apply or dismiss. The pricing, spend and agents guides say how.930 /** What each effort level has cost this agent, from its own finished sessions. Members only. */
931 effortCosts(workspace: string, handle: string, viewer: User): Promise<Result<AgentEffortCosts>>;
932 /** Ways to spend less, checked against past work: every agent's, or one's. Members only. */
933 recommendations(workspace: string, viewer: User, handle?: string | null): Promise<Result<AgentRecommendations>>;
934 /**
935 * Owners apply one (the agent's effort changes, as a new version, and
936 * the audit log says so) or dismiss it.
937 */
938 resolveRecommendation(workspace: string, viewer: User, id: string, action: "apply" | "dismiss"): Promise<Result<AgentRecommendation>>;
People and teams are front and centre: one directory of people and agents with presence, local time, titles, teams and what each owns; profiles with manager and reports and the agents they work with; an org chart with each team's agents beside the person who leads it; and teams of any mix, with a lead, a channel, a budget agents keep to and the agents on them. Every agent is told its teams each turn (who leads, who owns what, who's around and who to page), and the team page shows exactly what. Member management is Members and invites; the people and teams guide says how.939 /** What an agent is told about its teams this turn, word for word. Members only. */
940 teamContext(workspace: string, handle: string, viewer: User): Promise<Result<AgentTeamContext>>;
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked941 versions(workspace: string, handle: string, viewer: User): Promise<Result<AgentVersion[]>>;
Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar942 /**
943 * Internal, from chat: a person pressed an action on one of agents'
944 * cards. Agents checks they may, acts, and updates the card.
945 */
946 cardAction(input: AgentCardAction): Promise<Result<CardActionResult>>;
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked947 policy(workspace: string, viewer: User): Promise<Result<AgentPolicy>>;
948 setPolicy(workspace: string, viewer: User, policy: Partial<AgentPolicy>): Promise<Result<AgentPolicy>>;
The Marketplace is where a workspace finds what to add, reached from Apps: the agent catalog of roles with who already does each job and Add to workspace; every integration with whether it's connected; g1t's own extensions, listed as Soon; and requests, where members ask and owners add or turn down, each told by a notification. Underneath, an extension is a manifest (publisher and tier, source and version from a tag, scopes, the domains its data goes to, its page on g1tusercontent.com, no price) and an install pins its version with an off switch, a budget and the audit log. Apps lists only what was added from the Marketplace, with pins; g1t's own pages stay in their sidebars, and AI Gateway joins Workspace's. The marketplace guide says how.949 /**
950 * The Marketplace's install requests (./marketplace.ts): every one in the
951 * workspace for an owner, a member's own for anyone else.
952 */
953 installRequests(workspace: string, viewer: User): Promise<Result<InstallRequests>>;
954 /**
The Marketplace adds what g1t doesn't do and connects what you already use: extensions (Mail, Support, CRM, Recruiting, On-call, and bridges to a helpdesk, CRM or ERP you run, all Soon), starter kits, and integrations connected by the workspace or by each person; agents aren't installed there. Agent templates live in Agents, as starting points you configure, at Agents → Templates, and the Marketplace's old agent addresses lead there. The marketplace and agents guides say how.955 * A member asks the workspace's owners to add a listing
956 * (`extension:<id>` or `integration:<connector>`), and every owner is
957 * notified. Owners add
The Marketplace is where a workspace finds what to add, reached from Apps: the agent catalog of roles with who already does each job and Add to workspace; every integration with whether it's connected; g1t's own extensions, listed as Soon; and requests, where members ask and owners add or turn down, each told by a notification. Underneath, an extension is a manifest (publisher and tier, source and version from a tag, scopes, the domains its data goes to, its page on g1tusercontent.com, no price) and an install pins its version with an off switch, a budget and the audit log. Apps lists only what was added from the Marketplace, with pins; g1t's own pages stay in their sidebars, and AI Gateway joins Workspace's. The marketplace guide says how.958 * things themselves, so they don't ask. Asking again while a request for
959 * the same listing is open is a conflict.
960 */
961 requestInstall(workspace: string, viewer: User, listing: string, note?: string | null): Promise<Result<InstallRequest>>;
962 /** An owner marks a request added (`done`) or turns it down (`declined`); whoever asked is told. */
963 resolveInstallRequest(workspace: string, viewer: User, id: string, status: Exclude<InstallRequestStatus, "open">): Promise<Result<InstallRequest>>;
964 /** The extensions installed in the workspace; any member sees them. */
965 extensionInstalls(workspace: string, viewer: User): Promise<Result<ExtensionInstall[]>>;
966 /** Owners install a published extension at its current version; open requests for it are answered. */
967 installExtension(workspace: string, viewer: User, extension: string): Promise<Result<ExtensionInstall>>;
968 /** Owners switch an install on or off: off is the kill switch. */
969 setExtensionEnabled(workspace: string, viewer: User, listing: string, enabled: boolean): Promise<Result<ExtensionInstall>>;
970 /** Owners cap what an install spends a month; null leaves it to the workspace's limit. */
971 setExtensionBudget(workspace: string, viewer: User, listing: string, monthlyMicros: number | null): Promise<Result<ExtensionInstall>>;
972 uninstallExtension(workspace: string, viewer: User, listing: string): Promise<Result<null>>;
Chat and workspace agents: channels, DMs and named agents you talk to973};
974
975async function rpc<T>(service: ServiceBinding, method: string, args: object): Promise<T> {
976 const response = await service.fetch(`https://service/rpc/${method}`, {
977 method: "POST",
978 headers: { "content-type": "application/json" },
979 body: JSON.stringify(args),
980 });
981 if (!response.ok) {
982 throw new Error(`${method} failed with status ${response.status}`);
983 }
984 return (await response.json()) as T;
985}
986
People and teams are front and centre: one directory of people and agents with presence, local time, titles, teams and what each owns; profiles with manager and reports and the agents they work with; an org chart with each team's agents beside the person who leads it; and teams of any mix, with a lead, a channel, a budget agents keep to and the agents on them. Every agent is told its teams each turn (who leads, who owns what, who's around and who to page), and the team page shows exactly what. Member management is Members and invites; the people and teams guide says how.987/**
988 * What an agent is told about its teams every turn (docs.g1t.sh/guides/people-and-teams/,
989 * "What agents are told"): the visible teams it is on, by slug, and the text
990 * itself; null when it is on none.
991 */
992export type AgentTeamContext = { handle: string; teams: string[]; text: string | null };
993
Chat and workspace agents: channels, DMs and named agents you talk to994export function workspaceAgentsClient(service: ServiceBinding): WorkspaceAgentsApi {
995 const call = <T>(method: string, args: object) => rpc<T>(service, method, args);
996 return {
Anyone makes an agent by describing it: one box drafts the whole agent (name, job, responsibilities, voice, skills to keep, integrations it needs, model limits and budget) as a card to change and try in a chat beside it before creating it, and an agent changes later by saying what to change, shown as a diff before it's saved. Members can make personal agents, which only they talk to and which spend from their own budget, unless owners turn that off; owners promote one to a workspace agent. The agents guide says how.997 list: (workspace, viewer, options) => call("list", { workspace, viewer, personal: options?.personal ?? null }),
Chat and workspace agents: channels, DMs and named agents you talk to998 get: (workspace, handle, viewer) => call("get", { workspace, handle, viewer }),
999 byIds: (ids) => call("by_ids", { ids }),
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.1000 create: (workspace, viewer, input, options) => call("create", { workspace, viewer, input, teams: options?.teams ?? [] }),
Chat and workspace agents: channels, DMs and named agents you talk to1001 update: (workspace, handle, viewer, changes) => call("update", { workspace, handle, viewer, changes }),
1002 archive: (workspace, handle, viewer) => call("archive", { workspace, handle, viewer }),
Anyone makes an agent by describing it: one box drafts the whole agent (name, job, responsibilities, voice, skills to keep, integrations it needs, model limits and budget) as a card to change and try in a chat beside it before creating it, and an agent changes later by saying what to change, shown as a diff before it's saved. Members can make personal agents, which only they talk to and which spend from their own budget, unless owners turn that off; owners promote one to a workspace agent. The agents guide says how.1003 draft: (workspace, viewer, input) => call("draft", { workspace, viewer, description: input.description, scope: input.scope ?? null }),
1004 tryDraft: (workspace, viewer, input) => call("try_draft", { workspace, viewer, definition: input.definition, messages: input.messages }),
1005 redraft: (workspace, handle, viewer, request) => call("redraft", { workspace, handle, viewer, request }),
1006 promote: (workspace, handle, viewer) => call("promote", { workspace, handle, viewer }),
Each agent has an Abilities tab: g1t's built-ins, always on within the asker's access; its computer, coming; each connected integration's actions one row each, read, import, comment or resolve, with a level for each, alone, alone when the person asked for it, ask first or never, and whose connection it runs on; and MCP servers an owner adds. Reading is alone, writing inside g1t follows today's choices, anything that leaves g1t asks first, and production deploys can't go above ask. The agents service enforces every level: ask first posts a card to allow or deny and parks a session until it's answered, a refusal names its rule in the transcript and the audit log, and a missing ability posts a request to owners. The agent abilities guide says how.1007 addMcpServer: (workspace, handle, viewer, input) => call("add_mcp_server", { workspace, handle, viewer, name: input.name, url: input.url }),
1008 removeMcpServer: (workspace, handle, viewer, id) => call("remove_mcp_server", { workspace, handle, viewer, id }),
1009 refreshMcpServer: (workspace, handle, viewer, id) => call("refresh_mcp_server", { workspace, handle, viewer, id }),
Chat and workspace agents: channels, DMs and named agents you talk to1010 templates: () => call("templates", {}),
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)1011 builtin: (workspace, workspaceId) => call("builtin", { workspace, workspace_id: workspaceId }),
Chat and workspace agents: channels, DMs and named agents you talk to1012 deliver: (delivery) => call("deliver", delivery),
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked1013 overview: (workspace, viewer) => call("overview", { workspace, viewer }),
1014 sessions: (workspace, viewer, filter) => call("sessions", { workspace, viewer, ...(filter ?? {}) }),
1015 session: (workspace, id, viewer) => call("session", { workspace, id, viewer }),
1016 stopSession: (workspace, id, viewer) => call("stop_session", { workspace, id, viewer }),
1017 approveSession: (workspace, id, viewer, capMicros) => call("approve_session", { workspace, id, viewer, cap_micros: capMicros }),
1018 steerSession: (workspace, id, viewer, body) => call("steer_session", { workspace, id, viewer, body }),
1019 memories: (workspace, handle, viewer) => call("memories", { workspace, handle, viewer }),
1020 remember: (workspace, handle, viewer, input) => call("remember", { workspace, handle, viewer, input }),
1021 updateMemory: (workspace, handle, viewer, id, changes) => call("update_memory", { workspace, handle, viewer, id, changes }),
1022 forget: (workspace, handle, viewer, id) => call("forget", { workspace, handle, viewer, id }),
1023 routines: (workspace, handle, viewer) => call("routines", { workspace, handle, viewer }),
1024 saveRoutine: (workspace, handle, viewer, input, id) => call("save_routine", { workspace, handle, viewer, input, id: id ?? null }),
1025 deleteRoutine: (workspace, handle, viewer, id) => call("delete_routine", { workspace, handle, viewer, id }),
1026 runRoutine: (workspace, handle, viewer, id) => call("run_routine", { workspace, handle, viewer, id }),
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.1027 spend: (workspace, viewer, handle, options) =>
1028 call("spend", { workspace, viewer, handle: handle ?? null, period: options?.period ?? null, person: options?.person ?? null }),
1029 personBudgets: (workspace, viewer) => call("person_budgets", { workspace, viewer }),
People and teams are front and centre: one directory of people and agents with presence, local time, titles, teams and what each owns; profiles with manager and reports and the agents they work with; an org chart with each team's agents beside the person who leads it; and teams of any mix, with a lead, a channel, a budget agents keep to and the agents on them. Every agent is told its teams each turn (who leads, who owns what, who's around and who to page), and the team page shows exactly what. Member management is Members and invites; the people and teams guide says how.1030 teamContext: (workspace, handle, viewer) => call("team_context", { workspace, handle, viewer }),
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.1031 setPersonBudget: (workspace, viewer, username, monthlyMicros) =>
1032 call("set_person_budget", { workspace, viewer, username, monthly_micros: monthlyMicros }),
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked1033 activity: (workspace, handle, viewer) => call("activity", { workspace, handle, viewer }),
Pricing says it plainly: models at the provider's price, the agent rate for what g1t runs around every model call (the gateway, secrets, routing, context and pass-through to your own provider, so your own keys too), everything else at cost plus 20%, your own runners free, no seats; Security and quality comes with the plan with no separate fee, and live activations end. Each agent has an effort setting, Auto to Max, with what a typical task has cost at each level, and Spend's Spend less, keep quality suggests a lower level only when the agent's own past work shows quality held, to apply or dismiss. The pricing, spend and agents guides say how.1034 effortCosts: (workspace, handle, viewer) => call("effort_costs", { workspace, handle, viewer }),
1035 recommendations: (workspace, viewer, handle) => call("recommendations", { workspace, viewer, handle: handle ?? null }),
1036 resolveRecommendation: (workspace, viewer, id, action) => call("resolve_recommendation", { workspace, viewer, id, action }),
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked1037 versions: (workspace, handle, viewer) => call("versions", { workspace, handle, viewer }),
Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar1038 cardAction: (input) => call("card_action", input),
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked1039 policy: (workspace, viewer) => call("policy", { workspace, viewer }),
1040 setPolicy: (workspace, viewer, policy) => call("set_policy", { workspace, viewer, policy }),
The Marketplace is where a workspace finds what to add, reached from Apps: the agent catalog of roles with who already does each job and Add to workspace; every integration with whether it's connected; g1t's own extensions, listed as Soon; and requests, where members ask and owners add or turn down, each told by a notification. Underneath, an extension is a manifest (publisher and tier, source and version from a tag, scopes, the domains its data goes to, its page on g1tusercontent.com, no price) and an install pins its version with an off switch, a budget and the audit log. Apps lists only what was added from the Marketplace, with pins; g1t's own pages stay in their sidebars, and AI Gateway joins Workspace's. The marketplace guide says how.1041 installRequests: (workspace, viewer) => call("install_requests", { workspace, viewer }),
1042 requestInstall: (workspace, viewer, listing, note) => call("request_install", { workspace, viewer, listing, note: note ?? null }),
1043 resolveInstallRequest: (workspace, viewer, id, status) => call("resolve_install_request", { workspace, viewer, id, status }),
1044 extensionInstalls: (workspace, viewer) => call("extension_installs", { workspace, viewer }),
1045 installExtension: (workspace, viewer, extension) => call("install_extension", { workspace, viewer, extension }),
1046 setExtensionEnabled: (workspace, viewer, listing, enabled) => call("set_extension_enabled", { workspace, viewer, listing, enabled }),
1047 setExtensionBudget: (workspace, viewer, listing, monthlyMicros) => call("set_extension_budget", { workspace, viewer, listing, monthly_micros: monthlyMicros }),
1048 uninstallExtension: (workspace, viewer, listing) => call("uninstall_extension", { workspace, viewer, listing }),
Chat and workspace agents: channels, DMs and named agents you talk to1049 };
1050}

This file's history is long; its oldest lines are credited to the oldest commit read.