Skip to content
808 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";
Chat and workspace agents: channels, DMs and named agents you talk to18
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)19/** The built-in orchestrator's handle; nobody else's agent may take it. */
20export const BUILTIN_AGENT_HANDLE = "g1t";
21
22/** The built-in orchestrator's template id: not one a workspace can adopt. */
23export const ORCHESTRATOR_TEMPLATE = "orchestrator";
24
Chat and workspace agents: channels, DMs and named agents you talk to25/** Voice presets; free text in `personality` refines them. */
26export type PersonalityPreset = "crisp" | "friendly" | "socratic" | "terse";
27
28export type AgentRouting = {
29 /** Never route below this tier. Null: no floor. */
30 floor: ModelTier | null;
31 /** Never route above this tier. Null: no ceiling. */
32 ceiling: ModelTier | null;
33 /**
34 * Where its model calls may go. Empty: anything the workspace allows.
35 * `g1t`: g1t's hosted models. `workspace`: the workspace's own providers
36 * (Integrations), whichever they are. Any other entry: one of the
37 * workspace's own providers by integration id. Entries combine, so
38 * `["g1t", "workspace"]` is both.
39 */
40 providers: string[];
41 /** Advanced: a fixed `provider/model`, for own endpoints. Usually null. */
42 pinned: string | null;
43};
44
45export type AgentBudget = {
46 /** Monthly cap in micro-dollars. Null: only the workspace limit applies. */
47 monthly_micros: number | null;
48 daily_micros: number | null;
49 /** Default cap for one task. */
50 task_micros: number | null;
51};
52
53export type AgentAutonomy = {
54 open_pull_requests: "alone" | "approval";
55 merge: "alone" | "approval" | "never";
56 deploy_production: "approval" | "never";
57 edit_docs: "alone" | "suggest";
58};
59
60export type AgentStatus = "idle" | "working" | "waiting" | "out_of_budget" | "paused";
61
62export type WorkspaceAgent = {
63 id: string;
64 workspace_id: string;
65 /** Lowercase, unique in the workspace, never `g1t`. Mentioned as `@handle`. */
66 handle: string;
67 display_name: string;
68 /** Uploaded avatar hash, or null for the generated mark. */
69 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)70 /**
71 * What its generated avatar is drawn from: a little pixel creature, the
72 * same for the same seed everywhere. Set from the handle when it is
73 * made; changing it gives the agent a new face.
74 */
75 avatar_seed: string;
76 /**
77 * One line, as lists show it: "QA Engineer on the QA team". Made from
78 * the title and team (or department) when not written.
79 */
Chat and workspace agents: channels, DMs and named agents you talk to80 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)81 /**
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.82 * Agents are hired into roles, not tasks: a title, a team, and broad
83 * responsibilities.
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)84 */
85 title: string;
86 /** The team it is on, by slug, from the workspace's teams; null for none. */
87 team: string | null;
88 /** A label for where it works when it is on no team: "QA", "Sales". */
89 department: string;
90 /** What it is responsible for: 2 to 8 short duties, or none yet. */
91 responsibilities: string[];
92 /**
93 * Specialised help it will use inside its own work. Never members, never
94 * wider than their agent. Stored now; they run with tasks and sessions.
95 */
96 subagents: SubagentDef[];
97 /**
Agents recall what Docs say before they answer or work, and each has required reading98 * Its required reading: Docs spaces (by id) it checks first, every time
99 * it answers or works. It still reads only what the person it acts for,
100 * and everyone reading its answer, can read.
101 */
102 reading: string[];
103 /**
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.104 * g1t's foundational skills turned off for it, by id (./skills.ts):
105 * every one is on unless named here. Off takes the skill's playbook out of
106 * its instructions; its tools stay as they are.
107 */
108 skills_off: string[];
109 /**
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)110 * Who it works with: `internal`, the workspace's own people (back
111 * office), or `customers` (front office). Only `internal` for now.
112 */
113 faces: AgentFaces;
Chat and workspace agents: channels, DMs and named agents you talk to114 /** The job: what it is responsible for and how it works. */
115 instructions: string;
116 personality_preset: PersonalityPreset;
117 /** Free text refining the voice. Never changes what it may do. */
118 personality: string;
119 routing: AgentRouting;
120 budget: AgentBudget;
121 autonomy: AgentAutonomy;
122 /** Tasks it works at once; more queue on its desk. */
123 capacity: number;
124 /** The template it was made from, if any. */
125 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)126 /**
127 * The workspace's built-in orchestrator, `@g1t`: every workspace has one,
128 * made the first time its agents are asked for. It cannot be archived,
129 * and its handle, name, role and job are fixed; its `instructions` are
130 * added to that job. Listed first.
131 */
132 builtin: boolean;
Chat and workspace agents: channels, DMs and named agents you talk to133 version: number;
134 status: AgentStatus;
135 /** Spend this calendar month, in micro-dollars. */
136 spent_month_micros: number;
137 created_by: string;
138 created_at: string;
139 updated_at: string;
140 archived_at: string | null;
141};
142
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)143/**
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.144 * Back office or front office (docs.g1t.sh/guides/agents/, "Back office
145 * 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)146 */
147export type AgentFaces = "internal" | "customers";
148
149/**
150 * A subagent: help an agent keeps for its own work, such as Margo's
151 * `flake-hunter`. Its routing limits sit within its agent's: a floor below
152 * the agent's is raised to it, a ceiling above is lowered to it.
153 */
154export type SubagentDef = {
155 /** Lowercase letters, digits and hyphens: `flake-hunter`. Unique on the agent. */
156 name: string;
157 /** One line: what it is for. */
158 description: string;
159 instructions: string;
160 routing: { floor: ModelTier | null; ceiling: ModelTier | null };
161 /** How many of it may run at once inside one task, 1 to 8. */
162 max_parallel: number;
163};
164
Chat and workspace agents: channels, DMs and named agents you talk to165export type NewWorkspaceAgent = {
166 handle: string;
167 display_name: 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)168 /** Left out or empty: made from the title and team. */
169 role?: string;
170 title?: string;
171 team?: string | null;
172 department?: string;
173 responsibilities?: string[];
174 subagents?: SubagentDef[];
Agents recall what Docs say before they answer or work, and each has required reading175 /** Docs spaces (by id) it reads first; at most 10. */
176 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.177 /** Foundational skills to turn off, by id (./skills.ts). */
178 skills_off?: 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)179 /** Only `internal` for now; `customers` is refused. */
180 faces?: AgentFaces;
Chat and workspace agents: channels, DMs and named agents you talk to181 instructions: string;
182 personality_preset?: PersonalityPreset;
183 personality?: string;
184 routing?: Partial<AgentRouting>;
185 budget?: Partial<AgentBudget>;
186 autonomy?: Partial<AgentAutonomy>;
187 capacity?: number;
188 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)189 /** Its avatar's seed; left out, the handle. */
190 avatar_seed?: string;
Chat and workspace agents: channels, DMs and named agents you talk to191};
192
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)193/**
194 * A role to hire an agent into, by department. Agents get names, not job
195 * titles ("Margo", the QA Engineer).
196 */
Chat and workspace agents: channels, DMs and named agents you talk to197export type AgentTemplate = {
198 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)199 /** The name it suggests first. */
Chat and workspace agents: channels, DMs and named agents you talk to200 display_name: string;
201 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)202 /** Other names that suit it, for the form's shuffle. Each is also a valid handle, lowercased. */
203 name_ideas: string[];
Chat and workspace agents: channels, DMs and named agents you talk to204 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)205 title: string;
206 department: string;
207 responsibilities: string[];
208 subagents: SubagentDef[];
Chat and workspace agents: channels, DMs and named agents you talk to209 instructions: string;
210 personality_preset: PersonalityPreset;
211 routing: AgentRouting;
212};
213
214/** What the chat service hands an agent: a message it should answer. */
215export type AgentDelivery = {
216 workspace: string;
217 workspace_id: string;
218 channel_id: string;
219 channel_kind: "channel" | "dm";
220 channel_name: string | null;
221 agent_id: string;
222 /** The message that woke it. */
223 message_id: string;
224 thread_root: string | null;
225 /** Who asked: the person's user id. */
226 asked_by: string;
227 /** Agent-to-agent hops so far in this chain. */
228 hops: number;
229 /**
230 * What the person who asked may do, from the viewer the chat service
231 * 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.232 * never does more for someone than they could do themselves. Absent
233 * from an older chat service: the agent then treats the asker as unable
234 * to change code.
Chat and workspace agents: channels, DMs and named agents you talk to235 */
236 asker?: AskerAccess | null;
237 /**
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)238 * The agents that handled this request before this one, by id, oldest
239 * first; the last sent the work here. An agent never hands back or
240 * consults the one that sent it work, and the hop limit counts every
241 * hand-off and consult along the chain. Absent: none (a person asked).
242 */
243 chain?: string[];
244 /**
Chat and workspace agents: channels, DMs and named agents you talk to245 * 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.246 * the workspace connected. The agent reads and replies through that
247 * surface; its definition, budget and replies are the same everywhere.
248 * Absent: `g1t`.
Chat and workspace agents: channels, DMs and named agents you talk to249 */
250 surface?: AgentSurface;
251};
252
253/** The chat surfaces an agent answers on. Only g1t's own today. */
254export type AgentSurface = "g1t";
255
256/** Who asked an agent, as far as its reply needs to know. */
257export type AskerAccess = {
258 username: string;
259 /** Their role in the workspace; `outside` for someone who is not a member. */
260 role: Role | "outside";
261 /**
262 * Whether they can change code in the workspace: Code is on for them
263 * and they hold write access (or more) on at least one of its
264 * repositories, through the base permission or a grant.
265 */
266 can_write: boolean;
267};
268
269const WRITING_ROLES = new Set(["write", "maintain", "admin"]);
270
271/**
272 * `user`'s access in `workspace`, for `AgentDelivery.asker`. Pure, with no
273 * imports, so the chat service computes it from its viewer for free.
274 */
275export function askerAccess(user: User, workspace: string): AskerAccess {
276 const slug = workspace.toLowerCase();
277 const membership = user.workspaces?.find((m) => m.slug.toLowerCase() === slug);
278 // Someone who uses only Chat, Docs and agents sees no repository at all.
279 const code = membership?.code_access !== false;
280 const base = membership ? membership.role === "owner" || WRITING_ROLES.has(membership.base_permission ?? "write") : false;
281 const granted = (user.grants ?? []).some((grant) => grant.workspace.toLowerCase() === slug && WRITING_ROLES.has(grant.role));
282 return {
283 username: user.username,
284 role: membership?.role ?? "outside",
285 can_write: code && (base || granted),
286 };
287}
288
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 asked289/**
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.290 * A session: one bounded piece of work an agent took on
291 * (docs.g1t.sh/guides/agent-sessions/). A conversation with an agent is
292 * not a session: talking stays cheap and quick, and when a request needs
293 * 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 asked294 * the conversation. Sessions start other sessions (one of the agent's
295 * subagents, or a colleague brought in), and everything a tree of sessions
296 * spends is charged to the agent at its root, so a chain never escapes the
297 * budget that started it.
298 */
299export type AgentSessionKind =
300 /** Spun off from a conversation: someone asked for work. */
301 | "chat"
302 /** A routine's run. */
303 | "routine"
304 /** A colleague brought in by another session. */
305 | "helper"
306 /** One of the agent's own subagents, inside another session. */
307 | "subagent";
308
309export type AgentSessionStatus =
310 | "queued"
311 | "working"
312 /** Waiting on sessions it started. */
313 | "waiting"
314 /** Stopped at its spend cap: someone who may raise it decides. */
315 | "needs_approval"
316 | "done"
317 | "failed"
318 | "stopped";
319
320/** The statuses of a session that is not over. */
321export const SESSION_LIVE: readonly AgentSessionStatus[] = ["queued", "working", "waiting", "needs_approval"];
322
323export type AgentSession = {
324 id: string;
325 workspace_id: string;
326 agent_id: string;
327 /** The agent's handle, name and face, for lists. */
328 agent_handle: string;
329 agent_name: string;
330 agent_avatar_seed: string;
331 /** The subagent running it, by name, when kind is `subagent`. */
332 subagent: string | null;
333 kind: AgentSessionKind;
334 /** The session that started it, and the root of its tree. */
335 parent_id: string | null;
336 root_id: string;
337 /** Whose budget pays for it: the agent at the root of its tree. */
338 payer_agent_id: string;
339 title: string;
340 goal: string;
341 status: AgentSessionStatus;
342 /** Why it is waiting, stopped or failed, in a line. */
343 status_note: string | null;
344 /** What it found or did, once done: its report. */
345 summary: string | null;
346 /** Where it reports: the conversation it was started from. */
347 channel_id: string;
348 channel_kind: "channel" | "dm";
349 channel_name: string | null;
350 /** Its live card in that conversation; its updates go in the card's thread. */
351 card_message_id: string | null;
352 asked_by: string | null;
353 asked_by_username: string | null;
354 routine_id: string | null;
355 steps: number;
356 tool_calls: number;
357 input_tokens: number;
358 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.359 /**
360 * At list price, what it counts against budgets: the model at the
361 * provider's price with billing's model margin, plus g1t's agent rate on
362 * every token. A root session's includes everything its tree spent.
363 */
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 asked364 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.365 /** What its own steps' model answers cost at the provider's price, its tree's not included. */
366 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 asked367 /** The most it may spend before someone approves more. */
368 cap_micros: number | null;
369 model: string | null;
370 /** What it produced: issues filed, sessions started. */
371 outputs: SessionOutput[];
372 created_at: string;
373 updated_at: string;
374 finished_at: string | null;
375 /**
376 * False when the viewer is not among the people of the conversation it
377 * came from: they see that it ran and what it cost, never its title,
378 * goal, report or transcript.
379 */
380 visible: boolean;
381};
382
383export type SessionOutput =
384 | { kind: "issue"; repo: string; number: number; title: string }
385 | { kind: "session"; id: string; agent_handle: string; title: string }
386 | { kind: "memory"; id: string; body: string };
387
388/** One entry of a session's transcript, as its page shows it. */
389export type SessionEvent = {
390 seq: number;
391 kind: "goal" | "text" | "tool" | "steer" | "update" | "child" | "result" | "note";
392 /** Who: the agent's handle, a person's username (steering), or null for g1t's notes. */
393 by: string | null;
394 body: string;
395 /** For `tool`: the tool, and whether it read, was withheld, refused or failed. */
396 tool: string | null;
397 outcome: string | null;
398 created_at: string;
399};
400
401export type AgentSessionDetail = {
402 session: AgentSession;
403 events: SessionEvent[];
404 /** Every session in its tree, root first. */
405 tree: AgentSession[];
406 /** Whether the viewer may stop it, steer it, or approve more spend. */
407 can_stop: boolean;
408 can_steer: boolean;
409 can_approve: boolean;
410};
411
412/**
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.413 * What an agent remembers (docs.g1t.sh/guides/agent-memory/). Every fact
414 * carries where it came from, and its scope decides, in code, where it may
415 * 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 asked416 *
417 * - `workspace`: anywhere in the workspace. Owners write these, or an agent
418 * from a public channel, which every member can read already.
419 * - `channel`: only in that channel and its threads.
420 * - `person`: only in a direct message with that one person.
421 */
422export type AgentMemoryScope = "workspace" | "channel" | "person";
423
424export type AgentMemory = {
425 id: string;
426 agent_id: string;
427 scope: AgentMemoryScope;
428 /** The channel's id or the person's user id; empty for `workspace`. */
429 scope_ref: string;
430 /** The channel's name or the person's username, for display. */
431 scope_label: string | null;
432 body: string;
433 source_kind: "message" | "session" | "person";
434 /** A message id, a session id, or the username of who wrote it. */
435 source_ref: string | null;
436 source_label: string | null;
437 /** The channel the source is in, for a link. */
438 source_channel_id: string | null;
439 created_by: string;
440 created_by_kind: "agent" | "user";
441 pinned: boolean;
442 created_at: string;
443 updated_at: string;
444};
445
446/** When a routine runs, in UTC. */
447export type RoutineSchedule = {
448 every: "hour" | "day" | "weekday" | "week";
449 /** Minute of the hour, 0 to 59. */
450 minute: number;
451 /** Hour of the day (UTC), 0 to 23; not used for `hour`. */
452 hour: number;
453 /** Day of the week for `week`, 0 (Sunday) to 6. */
454 weekday: number;
455};
456
457/**
Routines run when something happens: a pull request ready for review or merged, checks or a deploy failing, an issue opened458 * 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.459 * (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 opened460 * thing that happened, in a repository its sponsor can read.
461 */
462export const ROUTINE_EVENTS = [
463 { key: "pull_ready", label: "A pull request is ready for review", hint: "Opened ready, or moved out of draft." },
464 { key: "pull_merged", label: "A pull request is merged", hint: "On any branch it targets." },
465 { key: "checks_failed", label: "Checks fail on a pull request", hint: "Its required checks failed or errored." },
466 { key: "issue_opened", label: "An issue is opened", hint: "By a person or an agent." },
467 { key: "deploy_failed", label: "A deploy fails", hint: "A production or preview deploy." },
468] as const;
469
470export type RoutineEvent = (typeof ROUTINE_EVENTS)[number]["key"];
471
472/**
Merge branch 'chat-sidebar' into fast-push473 * 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 asked474 * of support themes. Each run is a session posted in the routine's channel,
475 * paid from the agent's budget, and run with the access of the person who
476 * set it up (its sponsor), never more.
477 */
478export type AgentRoutine = {
479 id: string;
480 agent_id: string;
481 name: string;
482 instructions: string;
Routines run when something happens: a pull request ready for review or merged, checks or a deploy failing, an issue opened483 /** When it runs on a clock; null when it runs only on events. */
484 schedule: RoutineSchedule | null;
485 /** What it runs on; empty when it runs only on its schedule. */
486 events: RoutineEvent[];
487 /** Which repositories its events come from, by `workspace/name`; empty: every one its sponsor can read. */
488 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 asked489 channel_id: string;
490 channel_name: string | null;
491 sponsor: string;
492 sponsor_username: string | null;
493 enabled: boolean;
494 /** Why g1t paused it, when it did. */
495 paused_note: string | null;
496 next_run_at: string | null;
497 last_run_at: string | null;
498 last_session_id: string | null;
499 runs: number;
500 created_at: string;
501 updated_at: string;
502};
503
Routines run when something happens: a pull request ready for review or merged, checks or a deploy failing, an issue opened504/** A routine suggested from an agent's responsibilities, for an owner to add in one step. */
505export type RoutineSuggestion = { responsibility: string; routine: Omit<NewRoutine, "channel_id"> };
506
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 asked507export type NewRoutine = {
508 name: string;
509 instructions: string;
Routines run when something happens: a pull request ready for review or merged, checks or a deploy failing, an issue opened510 /** A schedule, events, or both; at least one. */
511 schedule: RoutineSchedule | null;
512 events?: RoutineEvent[];
513 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 asked514 /** A channel the agent is in, by id. */
515 channel_id: string;
516 enabled?: boolean;
517};
518
519/**
520 * The workspace's say over all its agents together, set by owners: one
521 * monthly budget across every agent, the budget a new agent starts with,
522 * and the cap a session starts with. The workspace's spend limit and AI
523 * credit (billing) sit above all of it.
524 */
525export type AgentPolicy = {
526 /** Every agent's spend together in a month. Null: only the workspace's spend limit. */
527 monthly_micros: number | null;
528 /** The monthly budget a new agent gets. Null: none. */
529 default_agent_monthly_micros: number | null;
530 /** The cap one session starts with, unless its agent's per-task cap is lower. */
531 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.532 /**
533 * What the agents working for one person (their replies and sessions,
534 * asked for by that person) may spend together in a month, unless the
535 * person has a budget of their own. Null: no budget per person.
536 */
537 person_monthly_micros: number | null;
538};
539
540/** One person's budget: what agents working for them may spend in a month, and what they have. */
541export type PersonBudget = {
542 username: string;
543 /** The budget that applies: their own, or the workspace's per-person default. Null: none. */
544 monthly_micros: number | null;
545 /** Whether it is their own, set by an owner, rather than the default. */
546 own: boolean;
547 /** What agents spent for them this month (UTC). */
548 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 asked549};
550
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.551/** Budgets per person: the default, and each person who has one of their own or has spent this month. */
552export type PersonBudgets = {
553 period: string;
554 default_micros: number | null;
555 /** Owners see everyone; anyone else sees only themselves. Most spent first. */
556 people: PersonBudget[];
557};
558
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 asked559export type SpendSlice = { key: string; label: string; micros: number; count: number };
560
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.561/** Which days a breakdown covers: this month (the default), last month, or the last 7 or 30 days, in UTC. */
562export type SpendPeriod = "month" | "last_month" | "7d" | "30d";
563
564/** 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 asked565export 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.566 /** `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 asked567 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.568 /** The span asked for, and its first and last day (`YYYY-MM-DD`, both included). */
569 span: SpendPeriod;
570 from: string;
571 until: string;
572 /** The one person it is about (work asked for by them), or null for everyone's. */
573 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 asked574 total_micros: number;
575 /** Chat replies, sessions, routines, helping colleagues. */
576 by_kind: SpendSlice[];
577 by_model: SpendSlice[];
578 /** Who asked: the work done for each person. */
579 by_person: SpendSlice[];
580 by_agent: SpendSlice[];
581 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.582 /**
583 * Where it was asked: a channel by id (labelled `#name`), direct
584 * messages together (`dm`), and channels the viewer can't read together
585 * (`private`).
586 */
587 by_channel: SpendSlice[];
588 /** 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 asked589 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.590 /** 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 asked591 days: { day: string; micros: number }[];
592};
593
594/** Agents mode's front page. */
595export type AgentsOverview = {
596 policy: AgentPolicy;
597 /** Every agent's spend this month, against the policy's budget. */
598 spent_month_micros: number;
599 /** The highest alert this month: 75, 90 or 100 (% of the workspace's agent budget). */
600 alert: number | null;
601 agents: WorkspaceAgent[];
602 /** Live sessions, counted by agent id, for the roster. */
603 live_by_agent: Record<string, number>;
604 /** Sessions live now that the viewer can see. */
605 live: AgentSession[];
606 /** Sessions waiting on the viewer: spend they may approve. */
607 waiting_on_you: AgentSession[];
608 /** Recently finished sessions the viewer can see. */
609 recent: AgentSession[];
Routines run when something happens: a pull request ready for review or merged, checks or a deploy failing, an issue opened610 /** 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 asked611 upcoming: (AgentRoutine & { agent_handle: string; agent_name: string })[];
612 spend: AgentSpendBreakdown;
613 can_manage: boolean;
614};
615
616/** One thing an agent did, for its Activity tab. */
617export type AgentActivity = {
618 id: string;
619 kind: "reply" | "session";
620 status: string;
621 channel_id: string;
622 channel_name: string | null;
623 /** The session's title; null for a reply or one the viewer can't see. */
624 title: string | null;
625 asked_by_username: string | null;
626 model: string | null;
627 tools: number;
628 charged_micros: number;
629 created_at: string;
630 visible: boolean;
631 /** For a reply, the message it posted; for a session, its id. */
632 ref: string | null;
633};
634
635export type AgentVersion = { version: number; changed_by: string; created_at: string; definition: Partial<NewWorkspaceAgent> };
636
Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar637/** A card action, as chat hands it to agents. */
638export type AgentCardAction = {
639 workspace: string;
640 channel_id: string;
641 message_id: string;
642 viewer: User;
643 card: { kind: string; ref: string | null };
644 action_id: string;
645 input: string | null;
646};
647
Chat and workspace agents: channels, DMs and named agents you talk to648export type WorkspaceAgentsApi = {
649 list(workspace: string, viewer: User): Promise<Result<WorkspaceAgent[]>>;
650 get(workspace: string, handle: string, viewer: User): Promise<Result<WorkspaceAgent>>;
651 /** Internal: by id, for the chat service resolving members. */
652 byIds(ids: string[]): Promise<WorkspaceAgent[]>;
653 create(workspace: string, viewer: User, input: NewWorkspaceAgent): Promise<Result<WorkspaceAgent>>;
654 update(
655 workspace: string,
656 handle: string,
657 viewer: User,
658 changes: Partial<NewWorkspaceAgent>,
659 ): Promise<Result<WorkspaceAgent>>;
660 archive(workspace: string, handle: string, viewer: User): Promise<Result<null>>;
661 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)662 /**
663 * Internal: the workspace's built-in `@g1t` agent, made if it does not
664 * exist yet. The chat service asks for it when someone mentions @g1t in
665 * a channel it is not in yet.
666 */
667 builtin(workspace: string, workspaceId: string): Promise<Result<WorkspaceAgent>>;
Chat and workspace agents: channels, DMs and named agents you talk to668 /** The chat service hands over a message for an agent to answer. Returns at once. */
669 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 asked670 overview(workspace: string, viewer: User): Promise<Result<AgentsOverview>>;
671 sessions(
672 workspace: string,
673 viewer: User,
674 filter?: { handle?: string | null; status?: "live" | "done" | null; limit?: number | null },
675 ): Promise<Result<AgentSession[]>>;
676 session(workspace: string, id: string, viewer: User): Promise<Result<AgentSessionDetail>>;
677 /** Stops a session and every session under it. */
678 stopSession(workspace: string, id: string, viewer: User): Promise<Result<AgentSession>>;
679 /** Raises a stopped session's cap and lets it go on. Owners only. */
680 approveSession(workspace: string, id: string, viewer: User, capMicros: number): Promise<Result<AgentSession>>;
681 /** A person's message to a session, running or finished: it reads it and goes on. */
682 steerSession(workspace: string, id: string, viewer: User, body: string): Promise<Result<AgentSession>>;
683 memories(workspace: string, handle: string, viewer: User): Promise<Result<AgentMemory[]>>;
684 remember(
685 workspace: string,
686 handle: string,
687 viewer: User,
688 input: { body: string; scope: AgentMemoryScope; scope_ref?: string | null },
689 ): Promise<Result<AgentMemory>>;
690 updateMemory(
691 workspace: string,
692 handle: string,
693 viewer: User,
694 id: string,
695 changes: { body?: string; pinned?: boolean },
696 ): Promise<Result<AgentMemory>>;
697 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 opened698 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 asked699 saveRoutine(workspace: string, handle: string, viewer: User, input: NewRoutine, id?: string | null): Promise<Result<AgentRoutine>>;
700 deleteRoutine(workspace: string, handle: string, viewer: User, id: string): Promise<Result<null>>;
701 /** Runs a routine now, as a session. */
702 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.703 /**
704 * Where the spend went: one agent's, or every agent's; this month unless
705 * `period` says otherwise; for everyone, or only the work one `person`
706 * (by username) asked for.
707 */
708 spend(workspace: string, viewer: User, handle?: string | null, options?: { period?: SpendPeriod | null; person?: string | null }): Promise<Result<AgentSpendBreakdown>>;
709 /** Budgets per person this month: owners see everyone's, anyone else their own. */
710 personBudgets(workspace: string, viewer: User): Promise<Result<PersonBudgets>>;
711 /**
712 * Gives one person a monthly budget of their own (`monthly_micros`; 0 for
713 * no budget at all), or with null puts them back on the default. Owners only.
714 */
715 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 asked716 activity(workspace: string, handle: string, viewer: User): Promise<Result<AgentActivity[]>>;
717 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 calendar718 /**
719 * Internal, from chat: a person pressed an action on one of agents'
720 * cards. Agents checks they may, acts, and updates the card.
721 */
722 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 asked723 policy(workspace: string, viewer: User): Promise<Result<AgentPolicy>>;
724 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.725 /**
726 * The Marketplace's install requests (./marketplace.ts): every one in the
727 * workspace for an owner, a member's own for anyone else.
728 */
729 installRequests(workspace: string, viewer: User): Promise<Result<InstallRequests>>;
730 /**
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.731 * A member asks the workspace's owners to add a listing
732 * (`extension:<id>` or `integration:<connector>`), and every owner is
733 * 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.734 * things themselves, so they don't ask. Asking again while a request for
735 * the same listing is open is a conflict.
736 */
737 requestInstall(workspace: string, viewer: User, listing: string, note?: string | null): Promise<Result<InstallRequest>>;
738 /** An owner marks a request added (`done`) or turns it down (`declined`); whoever asked is told. */
739 resolveInstallRequest(workspace: string, viewer: User, id: string, status: Exclude<InstallRequestStatus, "open">): Promise<Result<InstallRequest>>;
740 /** The extensions installed in the workspace; any member sees them. */
741 extensionInstalls(workspace: string, viewer: User): Promise<Result<ExtensionInstall[]>>;
742 /** Owners install a published extension at its current version; open requests for it are answered. */
743 installExtension(workspace: string, viewer: User, extension: string): Promise<Result<ExtensionInstall>>;
744 /** Owners switch an install on or off: off is the kill switch. */
745 setExtensionEnabled(workspace: string, viewer: User, listing: string, enabled: boolean): Promise<Result<ExtensionInstall>>;
746 /** Owners cap what an install spends a month; null leaves it to the workspace's limit. */
747 setExtensionBudget(workspace: string, viewer: User, listing: string, monthlyMicros: number | null): Promise<Result<ExtensionInstall>>;
748 uninstallExtension(workspace: string, viewer: User, listing: string): Promise<Result<null>>;
Chat and workspace agents: channels, DMs and named agents you talk to749};
750
751async function rpc<T>(service: ServiceBinding, method: string, args: object): Promise<T> {
752 const response = await service.fetch(`https://service/rpc/${method}`, {
753 method: "POST",
754 headers: { "content-type": "application/json" },
755 body: JSON.stringify(args),
756 });
757 if (!response.ok) {
758 throw new Error(`${method} failed with status ${response.status}`);
759 }
760 return (await response.json()) as T;
761}
762
763export function workspaceAgentsClient(service: ServiceBinding): WorkspaceAgentsApi {
764 const call = <T>(method: string, args: object) => rpc<T>(service, method, args);
765 return {
766 list: (workspace, viewer) => call("list", { workspace, viewer }),
767 get: (workspace, handle, viewer) => call("get", { workspace, handle, viewer }),
768 byIds: (ids) => call("by_ids", { ids }),
769 create: (workspace, viewer, input) => call("create", { workspace, viewer, input }),
770 update: (workspace, handle, viewer, changes) => call("update", { workspace, handle, viewer, changes }),
771 archive: (workspace, handle, viewer) => call("archive", { workspace, handle, viewer }),
772 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)773 builtin: (workspace, workspaceId) => call("builtin", { workspace, workspace_id: workspaceId }),
Chat and workspace agents: channels, DMs and named agents you talk to774 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 asked775 overview: (workspace, viewer) => call("overview", { workspace, viewer }),
776 sessions: (workspace, viewer, filter) => call("sessions", { workspace, viewer, ...(filter ?? {}) }),
777 session: (workspace, id, viewer) => call("session", { workspace, id, viewer }),
778 stopSession: (workspace, id, viewer) => call("stop_session", { workspace, id, viewer }),
779 approveSession: (workspace, id, viewer, capMicros) => call("approve_session", { workspace, id, viewer, cap_micros: capMicros }),
780 steerSession: (workspace, id, viewer, body) => call("steer_session", { workspace, id, viewer, body }),
781 memories: (workspace, handle, viewer) => call("memories", { workspace, handle, viewer }),
782 remember: (workspace, handle, viewer, input) => call("remember", { workspace, handle, viewer, input }),
783 updateMemory: (workspace, handle, viewer, id, changes) => call("update_memory", { workspace, handle, viewer, id, changes }),
784 forget: (workspace, handle, viewer, id) => call("forget", { workspace, handle, viewer, id }),
785 routines: (workspace, handle, viewer) => call("routines", { workspace, handle, viewer }),
786 saveRoutine: (workspace, handle, viewer, input, id) => call("save_routine", { workspace, handle, viewer, input, id: id ?? null }),
787 deleteRoutine: (workspace, handle, viewer, id) => call("delete_routine", { workspace, handle, viewer, id }),
788 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.789 spend: (workspace, viewer, handle, options) =>
790 call("spend", { workspace, viewer, handle: handle ?? null, period: options?.period ?? null, person: options?.person ?? null }),
791 personBudgets: (workspace, viewer) => call("person_budgets", { workspace, viewer }),
792 setPersonBudget: (workspace, viewer, username, monthlyMicros) =>
793 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 asked794 activity: (workspace, handle, viewer) => call("activity", { workspace, handle, viewer }),
795 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 calendar796 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 asked797 policy: (workspace, viewer) => call("policy", { workspace, viewer }),
798 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.799 installRequests: (workspace, viewer) => call("install_requests", { workspace, viewer }),
800 requestInstall: (workspace, viewer, listing, note) => call("request_install", { workspace, viewer, listing, note: note ?? null }),
801 resolveInstallRequest: (workspace, viewer, id, status) => call("resolve_install_request", { workspace, viewer, id, status }),
802 extensionInstalls: (workspace, viewer) => call("extension_installs", { workspace, viewer }),
803 installExtension: (workspace, viewer, extension) => call("install_extension", { workspace, viewer, extension }),
804 setExtensionEnabled: (workspace, viewer, listing, enabled) => call("set_extension_enabled", { workspace, viewer, listing, enabled }),
805 setExtensionBudget: (workspace, viewer, listing, monthlyMicros) => call("set_extension_budget", { workspace, viewer, listing, monthly_micros: monthlyMicros }),
806 uninstallExtension: (workspace, viewer, listing) => call("uninstall_extension", { workspace, viewer, listing }),
Chat and workspace agents: channels, DMs and named agents you talk to807 };
808}

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