Skip to content
1,184 linesCodeBlameRaw
1/**
2 * A workspace's own agents: named members with a job, a personality,
3 * routing limits and a budget, kept by the agents service
4 * (`services/agents`). Every workspace also has `@g1t`, its built-in
5 * orchestrator, kept the same way (`builtin`).
6 *
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";
12import type { CardActionResult } from "./chat";
13
14// Model tiers (`ModelTier`, `MODEL_TIERS`) are integrations.ts's, the
15// same ones runs are routed between.
16import type { ModelTier } from "./integrations";
17import type { InstallRequest, InstallRequestStatus, InstallRequests } from "./marketplace";
18import type { AgentAbilities, AgentAbilitiesChange, McpServer } from "./abilities";
19import type { AgentConnector, ConnectorInput, ConnectorSignIn, CustomizeBundle, Marketplace, PluginAgentTemplate, PluginDetail, PluginInstall, PluginListing, SkillListing, WorkspaceConnector } from "./customize";
20import type { SkillScope } from "./skill-library";
21import type { AgentLook } from "./agent-look";
22import type { AgentComputerCommand, AgentComputerStatus } from "./runner";
23
24/** The built-in orchestrator's handle; nobody else's agent may take it. */
25export const BUILTIN_AGENT_HANDLE = "g1t";
26
27/** The built-in orchestrator's template id: not one a workspace can adopt. */
28export const ORCHESTRATOR_TEMPLATE = "orchestrator";
29
30/** Voice presets; free text in `personality` refines them. */
31export type PersonalityPreset = "crisp" | "friendly" | "socratic" | "terse";
32
33export type AgentRouting = {
34 /** Never route below this tier. Null: no floor. */
35 floor: ModelTier | null;
36 /** Never route above this tier. Null: no ceiling. */
37 ceiling: ModelTier | null;
38 /**
39 * Where its model calls may go. Empty: anything the workspace allows.
40 * `g1t`: g1t's hosted models. `workspace`: the workspace's own providers
41 * (Integrations), whichever they are. Any other entry: one of the
42 * workspace's own providers by integration id. Entries combine, so
43 * `["g1t", "workspace"]` is both.
44 */
45 providers: string[];
46 /** Advanced: a fixed `provider/model`, for own endpoints. Usually null. */
47 pinned: string | null;
48 /**
49 * How hard it works (docs.g1t.sh/guides/agents/#effort): the tier its
50 * work starts on, how hard the model reasons, and how many steps a
51 * session may take. `auto` (the default; absent means it) picks per
52 * piece of work. The floor and ceiling still hold.
53 */
54 effort?: AgentEffort;
55};
56
57/** An agent's effort setting, cheapest first after `auto`. */
58export type AgentEffort = "auto" | "low" | "medium" | "high" | "max";
59
60export const AGENT_EFFORTS: readonly AgentEffort[] = ["auto", "low", "medium", "high", "max"];
61
62/** A level work actually ran at: what `auto` resolves to each time. */
63export type EffortLevel = Exclude<AgentEffort, "auto">;
64
65export const EFFORT_LEVELS: readonly EffortLevel[] = ["low", "medium", "high", "max"];
66
67export type AgentBudget = {
68 /** Monthly cap in micro-dollars. Null: only the workspace limit applies. */
69 monthly_micros: number | null;
70 daily_micros: number | null;
71 /** Default cap for one task. */
72 task_micros: number | null;
73};
74
75export type AgentAutonomy = {
76 open_pull_requests: "alone" | "approval";
77 merge: "alone" | "approval" | "never";
78 deploy_production: "approval" | "never";
79 edit_docs: "alone" | "suggest";
80};
81
82export type AgentStatus = "idle" | "working" | "waiting" | "out_of_budget" | "paused";
83
84export type WorkspaceAgent = {
85 id: string;
86 workspace_id: string;
87 /** Lowercase, unique in the workspace, never `g1t`. Mentioned as `@handle`. */
88 handle: string;
89 display_name: string;
90 /** Uploaded avatar hash, or null for the generated mark. */
91 avatar: string | null;
92 /**
93 * What its generated face is drawn from (./agent-look.ts `lookFromSeed`),
94 * the same for the same seed everywhere. Set from the handle when it is
95 * made; changing it gives the agent a new face.
96 */
97 avatar_seed: string;
98 /**
99 * Its face as its owner chose it, part by part (./agent-look.ts), or
100 * null: the face `avatar_seed` draws. Shown wherever the agent appears.
101 */
102 look: AgentLook | null;
103 /**
104 * One line, as lists show it: "QA Engineer". Its title when not written.
105 */
106 role: string;
107 /**
108 * Agents are hired into roles, not tasks: a title and broad
109 * responsibilities. The teams it is on are team memberships, as a
110 * person's are (identity `team_agents`), never part of the agent.
111 */
112 title: string;
113 /** What it is responsible for: 2 to 8 short duties, or none yet. */
114 responsibilities: string[];
115 /**
116 * Specialised help it will use inside its own work. Never members, never
117 * wider than their agent. Stored now; they run with tasks and sessions.
118 */
119 subagents: SubagentDef[];
120 /**
121 * Its required reading: Docs spaces (by id) it checks first, every time
122 * it answers or works. It still reads only what the person it acts for,
123 * and everyone reading its answer, can read.
124 */
125 reading: string[];
126 /**
127 * g1t's foundational skills turned off for it, by id (./skills.ts):
128 * every one is on unless named here. Off takes the skill's playbook out of
129 * its instructions; its tools stay as they are.
130 */
131 skills_off: string[];
132 /**
133 * What it may do (./abilities.ts, docs.g1t.sh/guides/agent-abilities/):
134 * its level and credentials for each ability it has a choice about, and
135 * the MCP servers an owner added to it. Empty means every default.
136 */
137 abilities: AgentAbilities;
138 /**
139 * Who it works with: `internal`, the workspace's own people (back
140 * office), or `customers` (front office). Only `internal` for now.
141 */
142 faces: AgentFaces;
143 /** The job: what it is responsible for and how it works. */
144 instructions: string;
145 personality_preset: PersonalityPreset;
146 /** Free text refining the voice. Never changes what it may do. */
147 personality: string;
148 routing: AgentRouting;
149 budget: AgentBudget;
150 autonomy: AgentAutonomy;
151 /** Tasks it works at once; more queue on its desk. */
152 capacity: number;
153 /** The template it was made from, if any. */
154 template: string | null;
155 /**
156 * The workspace's built-in orchestrator, `@g1t`: every workspace has one,
157 * made the first time its agents are asked for. It cannot be archived,
158 * and its handle, name, role and job are fixed; its `instructions` are
159 * added to that job. Listed first.
160 */
161 builtin: boolean;
162 /**
163 * Who it belongs to (docs.g1t.sh/guides/agents/, "Personal agents"):
164 * `workspace`, the workspace's own, which owners keep; or `personal`, a
165 * member's own, which only that member talks to, in their direct message
166 * with it, and whose spend counts against that member's budget.
167 */
168 scope: WorkspaceAgentScope;
169 /** For a personal agent, the member it belongs to: their user id and username. Null for a workspace agent. */
170 personal_owner_id: string | null;
171 personal_owner: string | null;
172 version: number;
173 status: AgentStatus;
174 /** Spend this calendar month, in micro-dollars. */
175 spent_month_micros: number;
176 created_by: string;
177 created_at: string;
178 updated_at: string;
179 archived_at: string | null;
180 /** Who archived it, by username; null while it is live, or for one archived before this was kept. */
181 archived_by?: string | null;
182};
183
184/**
185 * An archived agent as the Agents page's Archived section lists it
186 * (docs.g1t.sh/guides/agents/, "Archive, restore and delete"): enough to
187 * draw its row and to say what deleting it for good takes with it.
188 */
189export type ArchivedAgent = {
190 id: string;
191 handle: string;
192 display_name: string;
193 title: string;
194 role: string;
195 avatar: string | null;
196 avatar_seed: string;
197 look: AgentLook | null;
198 scope: WorkspaceAgentScope;
199 personal_owner: string | null;
200 archived_at: string;
201 archived_by: string | null;
202 /** What goes with it when it is deleted. */
203 counts: { sessions: number; replies: number; memories: number; routines: number };
204};
205
206/**
207 * Back office or front office (docs.g1t.sh/guides/agents/, "Back office
208 * and front office"). Customer-facing agents are not available yet.
209 */
210export type AgentFaces = "internal" | "customers";
211
212/** A workspace agent, which owners keep, or a member's personal agent. */
213export type WorkspaceAgentScope = "workspace" | "personal";
214
215/** What a personal agent starts with, unless its creator gives it other caps: $20 a month and $2 a session. */
216export const PERSONAL_AGENT_BUDGET = { monthly_micros: 20_000_000, daily_micros: null, task_micros: 2_000_000 } as const;
217
218/** Most personal agents one member keeps in a workspace. */
219export const MAX_PERSONAL_AGENTS = 10;
220
221/**
222 * A subagent: help an agent keeps for its own work, such as Margo's
223 * `flake-hunter`. Its routing limits sit within its agent's: a floor below
224 * the agent's is raised to it, a ceiling above is lowered to it.
225 */
226export type SubagentDef = {
227 /** Lowercase letters, digits and hyphens: `flake-hunter`. Unique on the agent. */
228 name: string;
229 /** One line: what it is for. */
230 description: string;
231 instructions: string;
232 routing: { floor: ModelTier | null; ceiling: ModelTier | null };
233 /** How many of it may run at once inside one task, 1 to 8. */
234 max_parallel: number;
235};
236
237export type NewWorkspaceAgent = {
238 handle: string;
239 display_name: string;
240 /** Left out or empty: its title. */
241 role?: string;
242 title?: string;
243 responsibilities?: string[];
244 subagents?: SubagentDef[];
245 /** Docs spaces (by id) it reads first; at most 10. */
246 reading?: string[];
247 /** Foundational skills to turn off, by id (./skills.ts). */
248 skills_off?: string[];
249 /**
250 * Its abilities' levels and credentials (./abilities.ts), whole: what is
251 * sent replaces what it had. MCP servers are added and removed with
252 * `addMcpServer` and `removeMcpServer`, never here.
253 */
254 abilities?: AgentAbilitiesChange;
255 /** Only `internal` for now; `customers` is refused. */
256 faces?: AgentFaces;
257 instructions: string;
258 personality_preset?: PersonalityPreset;
259 personality?: string;
260 routing?: Partial<AgentRouting>;
261 budget?: Partial<AgentBudget>;
262 autonomy?: Partial<AgentAutonomy>;
263 capacity?: number;
264 template?: string | null;
265 /** Its avatar's seed; left out, the handle. */
266 avatar_seed?: string;
267 /** Its face, chosen part by part (./agent-look.ts); null goes back to the seed's face. */
268 look?: AgentLook | null;
269 /**
270 * When creating: `workspace` (owners only, and their default) or
271 * `personal` (any member, when the workspace lets members make them; a
272 * member's default). Ignored on a change: an owner promotes instead.
273 */
274 scope?: WorkspaceAgentScope;
275};
276
277/**
278 * What g1t drafted from a description (docs.g1t.sh/guides/agents/,
279 * "Describe it"): a whole definition to edit before anything is saved,
280 * and what the agent will want around it. Nothing here is saved until the
281 * agent is created.
282 */
283export type AgentProposal = {
284 /** A complete definition, ready to create as it is. */
285 definition: NewWorkspaceAgent & { scope: WorkspaceAgentScope };
286 /** Other names that suit it, for the shuffle. */
287 name_ideas: string[];
288 /** Foundational skills it should keep on, by id (./skills.ts); the rest are off in `definition.skills_off`. */
289 skills: string[];
290 /** Integrations the job needs, from the catalog (./connectors.ts), with why. */
291 integrations: { id: string; why: string }[];
292 /** Routines that would suit it, to set up on its Routines tab once it exists. */
293 routines: { name: string; when: string; instructions: string }[];
294 /** What drafting it cost, charged to the person who asked (micro-dollars). */
295 charged_micros: number;
296};
297
298/** One line of a Try it conversation, held by the page, never saved. */
299export type DraftTurn = { role: "user" | "assistant"; content: string };
300
301/** A Try it answer, and what it cost the person trying it. */
302export type DraftReply = { text: string; charged_micros: number };
303
304/** Changes drafted from "Tell <name> what to change", to review before they are saved as a new version. */
305export type AgentRedraft = {
306 /** The changes to save, as `update` takes them: only fields that differ. */
307 changes: Partial<NewWorkspaceAgent>;
308 /** One line on what changed. */
309 summary: string;
310 /** The version it was drafted from. */
311 from_version: number;
312 charged_micros: number;
313};
314
315/**
316 * A role to hire an agent into, by title. Agents get names, not job
317 * titles ("Margo", the QA Engineer). A template never puts an agent on a
318 * team.
319 */
320export type AgentTemplate = {
321 id: string;
322 /** The name it suggests first. */
323 display_name: string;
324 handle: string;
325 /** Other names that suit it, for the form's shuffle. Each is also a valid handle, lowercased. */
326 name_ideas: string[];
327 role: string;
328 title: string;
329 responsibilities: string[];
330 subagents: SubagentDef[];
331 instructions: string;
332 personality_preset: PersonalityPreset;
333 routing: AgentRouting;
334};
335
336/** What the chat service hands an agent: a message it should answer. */
337export type AgentDelivery = {
338 workspace: string;
339 workspace_id: string;
340 channel_id: string;
341 channel_kind: "channel" | "dm";
342 channel_name: string | null;
343 agent_id: string;
344 /** The message that woke it. */
345 message_id: string;
346 thread_root: string | null;
347 /** Who asked: the person's user id. */
348 asked_by: string;
349 /** Agent-to-agent hops so far in this chain. */
350 hops: number;
351 /**
352 * What the person who asked may do, from the viewer the chat service
353 * already holds when the message is posted (`askerAccess`). An agent
354 * never does more for someone than they could do themselves. Absent
355 * from an older chat service: the agent then treats the asker as unable
356 * to change code.
357 */
358 asker?: AskerAccess | null;
359 /**
360 * The agents that handled this request before this one, by id, oldest
361 * first; the last sent the work here. An agent never hands back or
362 * consults the one that sent it work, and the hop limit counts every
363 * hand-off and consult along the chain. Absent: none (a person asked).
364 */
365 chain?: string[];
366 /**
367 * Where the conversation is: g1t's own chat, or later another chat app
368 * the workspace connected. The agent reads and replies through that
369 * surface; its definition, budget and replies are the same everywhere.
370 * Absent: `g1t`.
371 */
372 surface?: AgentSurface;
373};
374
375/** The chat surfaces an agent answers on. Only g1t's own today. */
376export type AgentSurface = "g1t";
377
378/** Who asked an agent, as far as its reply needs to know. */
379export type AskerAccess = {
380 username: string;
381 /** Their role in the workspace; `outside` for someone who is not a member. */
382 role: Role | "outside";
383 /**
384 * Whether they can change code in the workspace: Code is on for them
385 * and they hold write access (or more) on at least one of its
386 * repositories, through the base permission or a grant.
387 */
388 can_write: boolean;
389};
390
391const WRITING_ROLES = new Set(["write", "maintain", "admin"]);
392
393/**
394 * `user`'s access in `workspace`, for `AgentDelivery.asker`. Pure, with no
395 * imports, so the chat service computes it from its viewer for free.
396 */
397export function askerAccess(user: User, workspace: string): AskerAccess {
398 const slug = workspace.toLowerCase();
399 const membership = user.workspaces?.find((m) => m.slug.toLowerCase() === slug);
400 // Someone who uses only Chat, Docs and agents sees no repository at all.
401 const code = membership?.code_access !== false;
402 const base = membership ? membership.role === "owner" || WRITING_ROLES.has(membership.base_permission ?? "write") : false;
403 const granted = (user.grants ?? []).some((grant) => grant.workspace.toLowerCase() === slug && WRITING_ROLES.has(grant.role));
404 return {
405 username: user.username,
406 role: membership?.role ?? "outside",
407 can_write: code && (base || granted),
408 };
409}
410
411/**
412 * A session: one bounded piece of work an agent took on
413 * (docs.g1t.sh/guides/agent-sessions/). A conversation with an agent is
414 * not a session: talking stays cheap and quick, and when a request needs
415 * real work the agent spins off a session for it, with its own context, transcript, budget and live card in
416 * the conversation. Sessions start other sessions (one of the agent's
417 * subagents, or a colleague brought in), and everything a tree of sessions
418 * spends is charged to the agent at its root, so a chain never escapes the
419 * budget that started it.
420 */
421export type AgentSessionKind =
422 /** Spun off from a conversation: someone asked for work. */
423 | "chat"
424 /** A routine's run. */
425 | "routine"
426 /** A colleague brought in by another session. */
427 | "helper"
428 /** One of the agent's own subagents, inside another session. */
429 | "subagent";
430
431export type AgentSessionStatus =
432 | "queued"
433 | "working"
434 /** Waiting on sessions it started. */
435 | "waiting"
436 /** Stopped at its spend cap: someone who may raise it decides. */
437 | "needs_approval"
438 | "done"
439 | "failed"
440 | "stopped";
441
442/** The statuses of a session that is not over. */
443export const SESSION_LIVE: readonly AgentSessionStatus[] = ["queued", "working", "waiting", "needs_approval"];
444
445export type AgentSession = {
446 id: string;
447 workspace_id: string;
448 agent_id: string;
449 /** The agent's handle, name and face, for lists. */
450 agent_handle: string;
451 agent_name: string;
452 agent_avatar_seed: string;
453 agent_look: AgentLook | null;
454 /** The subagent running it, by name, when kind is `subagent`. */
455 subagent: string | null;
456 kind: AgentSessionKind;
457 /** The session that started it, and the root of its tree. */
458 parent_id: string | null;
459 root_id: string;
460 /** Whose budget pays for it: the agent at the root of its tree. */
461 payer_agent_id: string;
462 title: string;
463 goal: string;
464 status: AgentSessionStatus;
465 /** Why it is waiting, stopped or failed, in a line. */
466 status_note: string | null;
467 /** What it found or did, once done: its report. */
468 summary: string | null;
469 /** Where it reports: the conversation it was started from. */
470 channel_id: string;
471 channel_kind: "channel" | "dm";
472 channel_name: string | null;
473 /** Its live card in that conversation; its updates go in the card's thread. */
474 card_message_id: string | null;
475 asked_by: string | null;
476 asked_by_username: string | null;
477 routine_id: string | null;
478 steps: number;
479 tool_calls: number;
480 input_tokens: number;
481 output_tokens: number;
482 /**
483 * At list price, what it counts against budgets: the model at the
484 * provider's price with billing's model margin, plus g1t's agent rate on
485 * every token. A root session's includes everything its tree spent.
486 */
487 charged_micros: number;
488 /** What its own steps' model answers cost at the provider's price, its tree's not included. */
489 cost_micros: number;
490 /** The most it may spend before someone approves more. */
491 cap_micros: number | null;
492 model: string | null;
493 /** The effort level it ran at (the highest, when `auto` raised it); null for sessions from before effort was recorded. */
494 effort: EffortLevel | null;
495 /** What it produced: issues filed, sessions started. */
496 outputs: SessionOutput[];
497 created_at: string;
498 updated_at: string;
499 finished_at: string | null;
500 /**
501 * False when the viewer is not among the people of the conversation it
502 * came from: they see that it ran and what it cost, never its title,
503 * goal, report or transcript.
504 */
505 visible: boolean;
506};
507
508export type SessionOutput =
509 | { kind: "issue"; repo: string; number: number; title: string }
510 | { kind: "session"; id: string; agent_handle: string; title: string }
511 | { kind: "memory"; id: string; body: string };
512
513/** One entry of a session's transcript, as its page shows it. */
514export type SessionEvent = {
515 seq: number;
516 kind: "goal" | "text" | "tool" | "command" | "steer" | "update" | "child" | "result" | "note";
517 /** Who: the agent's handle, a person's username (steering), or null for g1t's notes. */
518 by: string | null;
519 /** For `command`: the command on its first line, then its output, cut. */
520 body: string;
521 /** For `tool`: the tool, and whether it read, was withheld, refused or failed. For `command`: the directory it ran in. */
522 tool: string | null;
523 /** For `command`: `exit <code> · <duration>`, with `timed out` or `truncated` when so. */
524 outcome: string | null;
525 created_at: string;
526};
527
528/** An agent's computer as its Computer tab shows it (docs.g1t.sh/guides/agents/, "Its computer"). */
529export type AgentComputerView = {
530 status: AgentComputerStatus;
531 /** The most recent commands, newest first. */
532 commands: AgentComputerCommand[];
533 /** Whether the viewer may wake, sleep and reset it: owners, and the member of a personal agent. */
534 can_manage: boolean;
535};
536
537export type AgentSessionDetail = {
538 session: AgentSession;
539 events: SessionEvent[];
540 /** Every session in its tree, root first. */
541 tree: AgentSession[];
542 /** Whether the viewer may stop it, steer it, or approve more spend. */
543 can_stop: boolean;
544 can_steer: boolean;
545 can_approve: boolean;
546};
547
548/**
549 * What an agent remembers (docs.g1t.sh/guides/agent-memory/). Every fact
550 * carries where it came from, and its scope decides, in code, where it may
551 * be recalled and who may see it:
552 *
553 * - `workspace`: anywhere in the workspace. Owners write these, or an agent
554 * from a public channel, which every member can read already.
555 * - `channel`: only in that channel and its threads.
556 * - `person`: only in a direct message with that one person.
557 */
558export type AgentMemoryScope = "workspace" | "channel" | "person";
559
560export type AgentMemory = {
561 id: string;
562 agent_id: string;
563 scope: AgentMemoryScope;
564 /** The channel's id or the person's user id; empty for `workspace`. */
565 scope_ref: string;
566 /** The channel's name or the person's username, for display. */
567 scope_label: string | null;
568 body: string;
569 source_kind: "message" | "session" | "person";
570 /** A message id, a session id, or the username of who wrote it. */
571 source_ref: string | null;
572 source_label: string | null;
573 /** The channel the source is in, for a link. */
574 source_channel_id: string | null;
575 created_by: string;
576 created_by_kind: "agent" | "user";
577 pinned: boolean;
578 created_at: string;
579 updated_at: string;
580};
581
582/** When a routine runs, in UTC. */
583export type RoutineSchedule = {
584 every: "hour" | "day" | "weekday" | "week";
585 /** Minute of the hour, 0 to 59. */
586 minute: number;
587 /** Hour of the day (UTC), 0 to 23; not used for `hour`. */
588 hour: number;
589 /** Day of the week for `week`, 0 (Sunday) to 6. */
590 weekday: number;
591};
592
593/**
594 * Things that happen in the workspace a routine can run on
595 * (docs.g1t.sh/guides/agent-routines/). Each run is one session about the one
596 * thing that happened, in a repository its sponsor can read.
597 */
598export const ROUTINE_EVENTS = [
599 { key: "pull_ready", label: "A pull request is ready for review", hint: "Opened ready, or moved out of draft." },
600 { key: "pull_merged", label: "A pull request is merged", hint: "On any branch it targets." },
601 { key: "checks_failed", label: "Checks fail on a pull request", hint: "Its required checks failed or errored." },
602 { key: "issue_opened", label: "An issue is opened", hint: "By a person or an agent." },
603 { key: "deploy_failed", label: "A deploy fails", hint: "A production or preview deploy." },
604] as const;
605
606export type RoutineEvent = (typeof ROUTINE_EVENTS)[number]["key"];
607
608/**
609 * A routine: work an agent does on a schedule or when something happens, such as Sam's Monday digest
610 * of support themes. Each run is a session posted in the routine's channel,
611 * paid from the agent's budget, and run with the access of the person who
612 * set it up (its sponsor), never more.
613 */
614export type AgentRoutine = {
615 id: string;
616 agent_id: string;
617 name: string;
618 instructions: string;
619 /** When it runs on a clock; null when it runs only on events. */
620 schedule: RoutineSchedule | null;
621 /** What it runs on; empty when it runs only on its schedule. */
622 events: RoutineEvent[];
623 /** Which repositories its events come from, by `workspace/name`; empty: every one its sponsor can read. */
624 repos: string[];
625 channel_id: string;
626 channel_name: string | null;
627 sponsor: string;
628 sponsor_username: string | null;
629 enabled: boolean;
630 /** Why g1t paused it, when it did. */
631 paused_note: string | null;
632 next_run_at: string | null;
633 last_run_at: string | null;
634 last_session_id: string | null;
635 runs: number;
636 created_at: string;
637 updated_at: string;
638};
639
640/** A routine suggested from an agent's responsibilities, for an owner to add in one step. */
641export type RoutineSuggestion = { responsibility: string; routine: Omit<NewRoutine, "channel_id"> };
642
643export type NewRoutine = {
644 name: string;
645 instructions: string;
646 /** A schedule, events, or both; at least one. */
647 schedule: RoutineSchedule | null;
648 events?: RoutineEvent[];
649 repos?: string[];
650 /** A channel the agent is in, by id. */
651 channel_id: string;
652 enabled?: boolean;
653};
654
655/**
656 * The workspace's say over all its agents together, set by owners: one
657 * monthly budget across every agent, the budget a new agent starts with,
658 * and the cap a session starts with. The workspace's spend limit and AI
659 * credit (billing) sit above all of it.
660 */
661export type AgentPolicy = {
662 /** Every agent's spend together in a month. Null: only the workspace's spend limit. */
663 monthly_micros: number | null;
664 /** The monthly budget a new agent gets. Null: none. */
665 default_agent_monthly_micros: number | null;
666 /** The cap one session starts with, unless its agent's per-task cap is lower. */
667 default_session_micros: number;
668 /**
669 * What the agents working for one person (their replies and sessions,
670 * asked for by that person) may spend together in a month, unless the
671 * person has a budget of their own. Null: no budget per person.
672 */
673 person_monthly_micros: number | null;
674 /**
675 * Whether members who aren't owners may create personal agents
676 * (docs.g1t.sh/guides/agents/, "Personal agents"). On unless an owner
677 * turns it off; off, existing personal agents keep working.
678 */
679 members_create_agents: boolean;
680};
681
682/** One person's budget: what agents working for them may spend in a month, and what they have. */
683export type PersonBudget = {
684 username: string;
685 /** The budget that applies: their own, or the workspace's per-person default. Null: none. */
686 monthly_micros: number | null;
687 /** Whether it is their own, set by an owner, rather than the default. */
688 own: boolean;
689 /** What agents spent for them this month (UTC). */
690 spent_micros: number;
691};
692
693/** Budgets per person: the default, and each person who has one of their own or has spent this month. */
694export type PersonBudgets = {
695 period: string;
696 default_micros: number | null;
697 /** Owners see everyone; anyone else sees only themselves. Most spent first. */
698 people: PersonBudget[];
699};
700
701export type SpendSlice = { key: string; label: string; micros: number; count: number };
702
703/** Which days a breakdown covers: this month (the default), last month, or the last 7 or 30 days, in UTC. */
704export type SpendPeriod = "month" | "last_month" | "7d" | "30d";
705
706/** Where an agent's (or every agent's) spend went over a period. */
707export type AgentSpendBreakdown = {
708 /** `YYYY-MM` for a month; for a span of days, the month it ends in. */
709 period: string;
710 /** The span asked for, and its first and last day (`YYYY-MM-DD`, both included). */
711 span: SpendPeriod;
712 from: string;
713 until: string;
714 /** The one person it is about (work asked for by them), or null for everyone's. */
715 person: string | null;
716 total_micros: number;
717 /** Chat replies, sessions, routines, helping colleagues. */
718 by_kind: SpendSlice[];
719 by_model: SpendSlice[];
720 /** Who asked: the work done for each person. */
721 by_person: SpendSlice[];
722 by_agent: SpendSlice[];
723 by_team: SpendSlice[];
724 /**
725 * Where it was asked: a channel by id (labelled `#name`), direct
726 * messages together (`dm`), and channels the viewer can't read together
727 * (`private`).
728 */
729 by_channel: SpendSlice[];
730 /** The costliest sessions in the period. */
731 top_sessions: AgentSession[];
732 /** Spend by day in the period. */
733 days: { day: string; micros: number }[];
734};
735
736/**
737 * What each effort level has cost one agent, from its own finished
738 * sessions (docs.g1t.sh/guides/spend/#effort): measured, never estimated
739 * from other agents or list prices. A level it has not run at has no
740 * figures.
741 */
742export type EffortCost = {
743 effort: EffortLevel;
744 /** Its sessions (with everything they brought in) that finished in the window. */
745 sessions: number;
746 /** The median charged for one of them: a typical task. Null with none. */
747 typical_micros: number | null;
748 /** Of those, the share finished with nobody having to step in: no steering, not stopped or failed. Null with none. */
749 accepted_share: number | null;
750};
751
752export type AgentEffortCosts = {
753 handle: string;
754 /** Its setting now. */
755 effort: AgentEffort;
756 /** Days of history the figures cover. */
757 window_days: number;
758 levels: EffortCost[];
759};
760
761/** One side of a recommendation's evidence: the agent's sessions at one level. */
762export type EffortEvidence = {
763 effort: EffortLevel;
764 sessions: number;
765 /** Finished with nobody having to step in. */
766 accepted: number;
767 typical_micros: number;
768 mean_micros: number;
769};
770
771/**
772 * A way to spend less without losing quality, checked against the agent's
773 * own past work (docs.g1t.sh/guides/spend/#spend-less-keep-quality). The
774 * weekly check proposes one only when the cheaper level's measured
775 * outcomes hold up; when there is too little history to tell, it says so
776 * (`thin`) instead of proposing anything.
777 */
778export type AgentRecommendation = {
779 id: string;
780 agent_id: string;
781 agent_handle: string;
782 agent_name: string;
783 agent_avatar_seed: string;
784 agent_look: AgentLook | null;
785 /** Lowering its effort setting. */
786 kind: "effort";
787 /** `thin`: not enough history to recommend anything yet. */
788 status: "open" | "applied" | "dismissed" | "thin";
789 from_effort: AgentEffort;
790 to_effort: EffortLevel;
791 /** What it says to do, in a line. */
792 title: string;
793 /** Why, from the numbers in `evidence`, in a sentence. */
794 reason: string;
795 /** What it was measured on: the level it runs at now, and the cheaper one. Null sides had no sessions. */
796 evidence: { window_days: number; current: EffortEvidence | null; cheaper: EffortEvidence | null; needed: number };
797 /** About what a month it would save at the recent pace, from the measured costs. Null when thin. */
798 saving_month_micros: number | null;
799 checked_at: string;
800 resolved_by: string | null;
801 resolved_at: string | null;
802};
803
804export type AgentRecommendations = {
805 /** When the check last ran for the workspace; null before the first. */
806 checked_at: string | null;
807 window_days: number;
808 /** To act on, largest saving first. */
809 open: AgentRecommendation[];
810 /** Agents with too little history to say. */
811 thin: AgentRecommendation[];
812 /** Applied or dismissed in the last 30 days. */
813 resolved: AgentRecommendation[];
814};
815
816/** Agents mode's front page. */
817export type AgentsOverview = {
818 policy: AgentPolicy;
819 /** Every agent's spend this month, against the policy's budget. */
820 spent_month_micros: number;
821 /** The highest alert this month: 75, 90 or 100 (% of the workspace's agent budget). */
822 alert: number | null;
823 agents: WorkspaceAgent[];
824 /** Live sessions, counted by agent id, for the roster. */
825 live_by_agent: Record<string, number>;
826 /** Sessions live now that the viewer can see. */
827 live: AgentSession[];
828 /** Sessions waiting on the viewer: spend they may approve. */
829 waiting_on_you: AgentSession[];
830 /** Recently finished sessions the viewer can see. */
831 recent: AgentSession[];
832 /** The next routines to run on a schedule. */
833 upcoming: (AgentRoutine & { agent_handle: string; agent_name: string })[];
834 spend: AgentSpendBreakdown;
835 can_manage: boolean;
836};
837
838/** One thing an agent did, for its Activity tab. */
839export type AgentActivity = {
840 id: string;
841 kind: "reply" | "session";
842 status: string;
843 channel_id: string;
844 channel_name: string | null;
845 /** The session's title; null for a reply or one the viewer can't see. */
846 title: string | null;
847 asked_by_username: string | null;
848 model: string | null;
849 tools: number;
850 charged_micros: number;
851 created_at: string;
852 visible: boolean;
853 /** For a reply, the message it posted; for a session, its id. */
854 ref: string | null;
855};
856
857export type AgentVersion = { version: number; changed_by: string; created_at: string; definition: Partial<NewWorkspaceAgent> };
858
859/** A card action, as chat hands it to agents. */
860export type AgentCardAction = {
861 workspace: string;
862 channel_id: string;
863 message_id: string;
864 viewer: User;
865 card: { kind: string; ref: string | null };
866 action_id: string;
867 input: string | null;
868};
869
870export type WorkspaceAgentsApi = {
871 /**
872 * The workspace's agents. Personal agents are left out unless asked
873 * for: `mine`, the viewer's own; `all`, every member's for an owner (the
874 * viewer's own for anyone else).
875 */
876 list(workspace: string, viewer: User, options?: { personal?: "mine" | "all" | null }): Promise<Result<WorkspaceAgent[]>>;
877 get(workspace: string, handle: string, viewer: User): Promise<Result<WorkspaceAgent>>;
878 /** Internal: by id, for the chat service resolving members. */
879 byIds(ids: string[]): Promise<WorkspaceAgent[]>;
880 /**
881 * `teams`: the workspace's teams to add it to as it is made, by slug,
882 * each one the viewer manages (owners and the team's maintainers). The
883 * membership is the team's, as anyone's is; a personal agent joins none.
884 */
885 create(workspace: string, viewer: User, input: NewWorkspaceAgent, options?: { teams?: string[] }): Promise<Result<WorkspaceAgent>>;
886 update(
887 workspace: string,
888 handle: string,
889 viewer: User,
890 changes: Partial<NewWorkspaceAgent>,
891 ): Promise<Result<WorkspaceAgent>>;
892 archive(workspace: string, handle: string, viewer: User): Promise<Result<null>>;
893 /**
894 * The workspace's archived agents, newest archived first: every one for
895 * an owner, their own archived personal agents for anyone else.
896 */
897 listArchived(workspace: string, viewer: User): Promise<Result<ArchivedAgent[]>>;
898 /**
899 * Brings an archived agent back, under its handle or `options.handle`.
900 * `conflict` when a live agent holds the handle. Owners any agent, a
901 * member their own personal one.
902 */
903 restore(workspace: string, handle: string, viewer: User, options?: { handle?: string | null; id?: string | null }): Promise<Result<WorkspaceAgent>>;
904 /**
905 * Deletes an archived agent for good: its definition and versions,
906 * sessions, replies, memories, routines, drafts and computer, and its
907 * chat memberships. Its messages stay in chat under its last name, and
908 * its spend on the workspace's statement. `confirm` must be the handle.
909 * A live agent is archived first (`invalid`). Owners any agent, a member
910 * their own personal one; a second call is `not_found`.
911 */
912 destroy(workspace: string, handle: string, viewer: User, confirm: string, options?: { id?: string | null }): Promise<Result<null>>;
913 /**
914 * Drafts a whole agent from a description, with a fast model call charged
915 * to the viewer. Nothing is saved. Whoever may create the agent may draft it.
916 */
917 draft(workspace: string, viewer: User, input: { description: string; scope?: WorkspaceAgentScope | null }): Promise<Result<AgentProposal>>;
918 /**
919 * Try it: the unsaved definition answers the conversation so far, as it
920 * would in a direct message, without tools or memory. Charged to the
921 * viewer; nothing is saved.
922 */
923 tryDraft(workspace: string, viewer: User, input: { definition: NewWorkspaceAgent; messages: DraftTurn[] }): Promise<Result<DraftReply>>;
924 /** Drafts changes to an agent from a request in words; saved only through `update`. Whoever may change the agent may ask. */
925 redraft(workspace: string, handle: string, viewer: User, request: string): Promise<Result<AgentRedraft>>;
926 /**
927 * Owners make a member's personal agent a workspace agent: its definition
928 * and every version move to a workspace agent with the same handle, and
929 * the personal one is archived, with its memory and direct messages.
930 */
931 promote(workspace: string, handle: string, viewer: User): Promise<Result<WorkspaceAgent>>;
932 /**
933 * Adds an MCP server to an agent (docs.g1t.sh/guides/agent-abilities/,
934 * "MCP servers"): its host is checked, its tools are listed from it, and
935 * the agent gets a new version with each tool as an ability. Owners only.
936 */
937 addMcpServer(workspace: string, handle: string, viewer: User, input: { name: string; url: string }): Promise<Result<McpServer>>;
938 /** Takes an MCP server off an agent, with its abilities: a new version. Owners only. */
939 removeMcpServer(workspace: string, handle: string, viewer: User, id: string): Promise<Result<null>>;
940 /** Lists a server's tools again, for one that changed; a new version when they did. Owners only. */
941 refreshMcpServer(workspace: string, handle: string, viewer: User, id: string): Promise<Result<McpServer>>;
942 templates(): Promise<AgentTemplate[]>;
943 /**
944 * Internal: the workspace's built-in `@g1t` agent, made if it does not
945 * exist yet. The chat service asks for it when someone mentions @g1t in
946 * a channel it is not in yet.
947 */
948 builtin(workspace: string, workspaceId: string): Promise<Result<WorkspaceAgent>>;
949 /** The chat service hands over a message for an agent to answer. Returns at once. */
950 deliver(delivery: AgentDelivery): Promise<Result<null>>;
951 overview(workspace: string, viewer: User): Promise<Result<AgentsOverview>>;
952 sessions(
953 workspace: string,
954 viewer: User,
955 filter?: { handle?: string | null; status?: "live" | "done" | null; limit?: number | null },
956 ): Promise<Result<AgentSession[]>>;
957 session(workspace: string, id: string, viewer: User): Promise<Result<AgentSessionDetail>>;
958 /** Stops a session and every session under it. */
959 stopSession(workspace: string, id: string, viewer: User): Promise<Result<AgentSession>>;
960 /** Raises a stopped session's cap and lets it go on. Owners only. */
961 approveSession(workspace: string, id: string, viewer: User, capMicros: number): Promise<Result<AgentSession>>;
962 /** A person's message to a session, running or finished: it reads it and goes on. */
963 steerSession(workspace: string, id: string, viewer: User, body: string): Promise<Result<AgentSession>>;
964 /**
965 * The agent's computer: its state, disk and recent commands. Anyone who
966 * may see the agent; `can_manage` says whether the viewer may act on it.
967 */
968 computer(workspace: string, handle: string, viewer: User): Promise<Result<AgentComputerView>>;
969 /** Wakes it, restoring its home; metered until it sleeps. Owners, or a personal agent's member. */
970 wakeComputer(workspace: string, handle: string, viewer: User): Promise<Result<AgentComputerView>>;
971 /** Saves its home and stops it. Owners, or a personal agent's member. */
972 sleepComputer(workspace: string, handle: string, viewer: User): Promise<Result<AgentComputerView>>;
973 /** Wipes its home and its command history; memory and artifacts are kept. Owners, or a personal agent's member. */
974 resetComputer(workspace: string, handle: string, viewer: User): Promise<Result<AgentComputerView>>;
975 /** Its recent commands, newest first; `sessionId` narrows them to one session's. */
976 computerCommands(workspace: string, handle: string, viewer: User, sessionId?: string | null): Promise<Result<AgentComputerCommand[]>>;
977 memories(workspace: string, handle: string, viewer: User): Promise<Result<AgentMemory[]>>;
978 remember(
979 workspace: string,
980 handle: string,
981 viewer: User,
982 input: { body: string; scope: AgentMemoryScope; scope_ref?: string | null },
983 ): Promise<Result<AgentMemory>>;
984 updateMemory(
985 workspace: string,
986 handle: string,
987 viewer: User,
988 id: string,
989 changes: { body?: string; pinned?: boolean },
990 ): Promise<Result<AgentMemory>>;
991 forget(workspace: string, handle: string, viewer: User, id: string): Promise<Result<null>>;
992 routines(workspace: string, handle: string, viewer: User): Promise<Result<{ routines: AgentRoutine[]; suggestions: RoutineSuggestion[] }>>;
993 saveRoutine(workspace: string, handle: string, viewer: User, input: NewRoutine, id?: string | null): Promise<Result<AgentRoutine>>;
994 deleteRoutine(workspace: string, handle: string, viewer: User, id: string): Promise<Result<null>>;
995 /** Runs a routine now, as a session. */
996 runRoutine(workspace: string, handle: string, viewer: User, id: string): Promise<Result<AgentSession>>;
997 /**
998 * Where the spend went: one agent's, or every agent's; this month unless
999 * `period` says otherwise; for everyone, or only the work one `person`
1000 * (by username) asked for.
1001 */
1002 spend(workspace: string, viewer: User, handle?: string | null, options?: { period?: SpendPeriod | null; person?: string | null }): Promise<Result<AgentSpendBreakdown>>;
1003 /** Budgets per person this month: owners see everyone's, anyone else their own. */
1004 personBudgets(workspace: string, viewer: User): Promise<Result<PersonBudgets>>;
1005 /**
1006 * Gives one person a monthly budget of their own (`monthly_micros`; 0 for
1007 * no budget at all), or with null puts them back on the default. Owners only.
1008 */
1009 setPersonBudget(workspace: string, viewer: User, username: string, monthlyMicros: number | null): Promise<Result<PersonBudgets>>;
1010 activity(workspace: string, handle: string, viewer: User): Promise<Result<AgentActivity[]>>;
1011 /** What each effort level has cost this agent, from its own finished sessions. Members only. */
1012 effortCosts(workspace: string, handle: string, viewer: User): Promise<Result<AgentEffortCosts>>;
1013 /** Ways to spend less, checked against past work: every agent's, or one's. Members only. */
1014 recommendations(workspace: string, viewer: User, handle?: string | null): Promise<Result<AgentRecommendations>>;
1015 /**
1016 * Owners apply one (the agent's effort changes, as a new version, and
1017 * the audit log says so) or dismiss it.
1018 */
1019 resolveRecommendation(workspace: string, viewer: User, id: string, action: "apply" | "dismiss"): Promise<Result<AgentRecommendation>>;
1020 /** What an agent is told about its teams this turn, word for word. Members only. */
1021 teamContext(workspace: string, handle: string, viewer: User): Promise<Result<AgentTeamContext>>;
1022 versions(workspace: string, handle: string, viewer: User): Promise<Result<AgentVersion[]>>;
1023 /**
1024 * Internal, from chat: a person pressed an action on one of agents'
1025 * cards. Agents checks they may, acts, and updates the card.
1026 */
1027 cardAction(input: AgentCardAction): Promise<Result<CardActionResult>>;
1028 policy(workspace: string, viewer: User): Promise<Result<AgentPolicy>>;
1029 setPolicy(workspace: string, viewer: User, policy: Partial<AgentPolicy>): Promise<Result<AgentPolicy>>;
1030 /**
1031 * The Marketplace's install requests (./marketplace.ts): every one in the
1032 * workspace for an owner, a member's own for anyone else.
1033 */
1034 installRequests(workspace: string, viewer: User): Promise<Result<InstallRequests>>;
1035 /**
1036 * A member asks the workspace's owners to add a listing
1037 * (`extension:<id>` or `integration:<connector>`), and every owner is
1038 * notified. Owners add
1039 * things themselves, so they don't ask. Asking again while a request for
1040 * the same listing is open is a conflict.
1041 */
1042 requestInstall(workspace: string, viewer: User, listing: string, note?: string | null): Promise<Result<InstallRequest>>;
1043 /** An owner marks a request added (`done`) or turns it down (`declined`); whoever asked is told. */
1044 resolveInstallRequest(workspace: string, viewer: User, id: string, status: Exclude<InstallRequestStatus, "open">): Promise<Result<InstallRequest>>;
1045 /** The extensions installed in the workspace; any member sees them. */
1046 // Customize (./customize.ts): marketplaces, plugins and connectors.
1047 marketplaces(workspace: string, viewer: User): Promise<Result<Marketplace[]>>;
1048 addMarketplace(workspace: string, viewer: User, address: string, name?: string | null): Promise<Result<Marketplace>>;
1049 removeMarketplace(workspace: string, viewer: User, name: string): Promise<Result<null>>;
1050 refreshMarketplace(workspace: string, viewer: User, name: string): Promise<Result<Marketplace>>;
1051 discover(workspace: string, viewer: User): Promise<Result<{ plugins: PluginListing[]; skills: SkillListing[]; marketplaces: Marketplace[] }>>;
1052 plugin(workspace: string, viewer: User, ref: string): Promise<Result<PluginDetail>>;
1053 pluginInstalls(workspace: string, viewer: User): Promise<Result<PluginInstall[]>>;
1054 installPlugin(workspace: string, viewer: User, ref: string): Promise<Result<PluginInstall>>;
1055 setPluginEnabled(workspace: string, viewer: User, ref: string, enabled: boolean): Promise<Result<PluginInstall>>;
1056 uninstallPlugin(workspace: string, viewer: User, ref: string): Promise<Result<null>>;
1057 /** Reads an installed plugin again at its marketplace's current listing: new skill versions, subagents and servers; attachments follow. */
1058 updatePlugin(workspace: string, viewer: User, ref: string): Promise<Result<PluginInstall>>;
1059 pluginAgents(workspace: string, viewer: User): Promise<Result<PluginAgentTemplate[]>>;
1060 connectors(workspace: string, viewer: User): Promise<Result<WorkspaceConnector[]>>;
1061 connector(workspace: string, viewer: User, id: string): Promise<Result<WorkspaceConnector>>;
1062 addConnector(workspace: string, viewer: User, input: ConnectorInput): Promise<Result<WorkspaceConnector>>;
1063 setConnectorKey(workspace: string, viewer: User, id: string, headerName: string | null, value: string): Promise<Result<WorkspaceConnector>>;
1064 removeConnector(workspace: string, viewer: User, id: string): Promise<Result<null>>;
1065 refreshConnector(workspace: string, viewer: User, id: string): Promise<Result<WorkspaceConnector>>;
1066 /** Where the browser goes to sign the connector in; `redirectUri` is this g1t's page the server sends it back to. */
1067 startConnectorSignIn(workspace: string, viewer: User, id: string, redirectUri: string): Promise<Result<ConnectorSignIn>>;
1068 finishConnectorSignIn(workspace: string, viewer: User, state: string, code: string): Promise<Result<WorkspaceConnector>>;
1069 signOutConnector(workspace: string, viewer: User, id: string): Promise<Result<WorkspaceConnector>>;
1070 /** `target`: an agent's handle or a team's slug; null for every agent. */
1071 grantConnector(workspace: string, viewer: User, id: string, scope: SkillScope, target: string | null): Promise<Result<WorkspaceConnector>>;
1072 revokeConnector(workspace: string, viewer: User, id: string, grant: string): Promise<Result<WorkspaceConnector>>;
1073 agentConnectors(workspace: string, handle: string, viewer: User): Promise<Result<AgentConnector[]>>;
1074 /** What a job's Claude Code gets, read with the job's agent token; secrets included, so only the API hands it to a runner. */
1075 customizeBundle(workspace: string, viewer: User): Promise<Result<CustomizeBundle>>;
1076 /** Owners install a published extension at its current version; open requests for it are answered. */
1077 /** Owners switch an install on or off: off is the kill switch. */
1078 /** Owners cap what an install spends a month; null leaves it to the workspace's limit. */
1079};
1080
1081async function rpc<T>(service: ServiceBinding, method: string, args: object): Promise<T> {
1082 const response = await service.fetch(`https://service/rpc/${method}`, {
1083 method: "POST",
1084 headers: { "content-type": "application/json" },
1085 body: JSON.stringify(args),
1086 });
1087 if (!response.ok) {
1088 throw new Error(`${method} failed with status ${response.status}`);
1089 }
1090 return (await response.json()) as T;
1091}
1092
1093/**
1094 * What an agent is told about its teams every turn (docs.g1t.sh/guides/people-and-teams/,
1095 * "What agents are told"): the visible teams it is on, by slug, and the text
1096 * itself; null when it is on none.
1097 */
1098export type AgentTeamContext = { handle: string; teams: string[]; text: string | null };
1099
1100export function workspaceAgentsClient(service: ServiceBinding): WorkspaceAgentsApi {
1101 const call = <T>(method: string, args: object) => rpc<T>(service, method, args);
1102 return {
1103 list: (workspace, viewer, options) => call("list", { workspace, viewer, personal: options?.personal ?? null }),
1104 get: (workspace, handle, viewer) => call("get", { workspace, handle, viewer }),
1105 byIds: (ids) => call("by_ids", { ids }),
1106 create: (workspace, viewer, input, options) => call("create", { workspace, viewer, input, teams: options?.teams ?? [] }),
1107 update: (workspace, handle, viewer, changes) => call("update", { workspace, handle, viewer, changes }),
1108 archive: (workspace, handle, viewer) => call("archive", { workspace, handle, viewer }),
1109 listArchived: (workspace, viewer) => call("list_archived", { workspace, viewer }),
1110 restore: (workspace, handle, viewer, options) => call("restore", { workspace, handle, viewer, id: options?.id ?? null, new_handle: options?.handle ?? null }),
1111 destroy: (workspace, handle, viewer, confirm, options) => call("destroy", { workspace, handle, viewer, confirm, id: options?.id ?? null }),
1112 draft: (workspace, viewer, input) => call("draft", { workspace, viewer, description: input.description, scope: input.scope ?? null }),
1113 tryDraft: (workspace, viewer, input) => call("try_draft", { workspace, viewer, definition: input.definition, messages: input.messages }),
1114 redraft: (workspace, handle, viewer, request) => call("redraft", { workspace, handle, viewer, request }),
1115 promote: (workspace, handle, viewer) => call("promote", { workspace, handle, viewer }),
1116 addMcpServer: (workspace, handle, viewer, input) => call("add_mcp_server", { workspace, handle, viewer, name: input.name, url: input.url }),
1117 removeMcpServer: (workspace, handle, viewer, id) => call("remove_mcp_server", { workspace, handle, viewer, id }),
1118 refreshMcpServer: (workspace, handle, viewer, id) => call("refresh_mcp_server", { workspace, handle, viewer, id }),
1119 templates: () => call("templates", {}),
1120 builtin: (workspace, workspaceId) => call("builtin", { workspace, workspace_id: workspaceId }),
1121 deliver: (delivery) => call("deliver", delivery),
1122 overview: (workspace, viewer) => call("overview", { workspace, viewer }),
1123 sessions: (workspace, viewer, filter) => call("sessions", { workspace, viewer, ...(filter ?? {}) }),
1124 session: (workspace, id, viewer) => call("session", { workspace, id, viewer }),
1125 stopSession: (workspace, id, viewer) => call("stop_session", { workspace, id, viewer }),
1126 approveSession: (workspace, id, viewer, capMicros) => call("approve_session", { workspace, id, viewer, cap_micros: capMicros }),
1127 steerSession: (workspace, id, viewer, body) => call("steer_session", { workspace, id, viewer, body }),
1128 computer: (workspace, handle, viewer) => call("computer", { workspace, handle, viewer }),
1129 wakeComputer: (workspace, handle, viewer) => call("computer_wake", { workspace, handle, viewer }),
1130 sleepComputer: (workspace, handle, viewer) => call("computer_sleep", { workspace, handle, viewer }),
1131 resetComputer: (workspace, handle, viewer) => call("computer_reset", { workspace, handle, viewer }),
1132 computerCommands: (workspace, handle, viewer, sessionId) => call("computer_commands", { workspace, handle, viewer, session_id: sessionId ?? null }),
1133 memories: (workspace, handle, viewer) => call("memories", { workspace, handle, viewer }),
1134 remember: (workspace, handle, viewer, input) => call("remember", { workspace, handle, viewer, input }),
1135 updateMemory: (workspace, handle, viewer, id, changes) => call("update_memory", { workspace, handle, viewer, id, changes }),
1136 forget: (workspace, handle, viewer, id) => call("forget", { workspace, handle, viewer, id }),
1137 routines: (workspace, handle, viewer) => call("routines", { workspace, handle, viewer }),
1138 saveRoutine: (workspace, handle, viewer, input, id) => call("save_routine", { workspace, handle, viewer, input, id: id ?? null }),
1139 deleteRoutine: (workspace, handle, viewer, id) => call("delete_routine", { workspace, handle, viewer, id }),
1140 runRoutine: (workspace, handle, viewer, id) => call("run_routine", { workspace, handle, viewer, id }),
1141 spend: (workspace, viewer, handle, options) =>
1142 call("spend", { workspace, viewer, handle: handle ?? null, period: options?.period ?? null, person: options?.person ?? null }),
1143 personBudgets: (workspace, viewer) => call("person_budgets", { workspace, viewer }),
1144 teamContext: (workspace, handle, viewer) => call("team_context", { workspace, handle, viewer }),
1145 setPersonBudget: (workspace, viewer, username, monthlyMicros) =>
1146 call("set_person_budget", { workspace, viewer, username, monthly_micros: monthlyMicros }),
1147 activity: (workspace, handle, viewer) => call("activity", { workspace, handle, viewer }),
1148 effortCosts: (workspace, handle, viewer) => call("effort_costs", { workspace, handle, viewer }),
1149 recommendations: (workspace, viewer, handle) => call("recommendations", { workspace, viewer, handle: handle ?? null }),
1150 resolveRecommendation: (workspace, viewer, id, action) => call("resolve_recommendation", { workspace, viewer, id, action }),
1151 versions: (workspace, handle, viewer) => call("versions", { workspace, handle, viewer }),
1152 cardAction: (input) => call("card_action", input),
1153 policy: (workspace, viewer) => call("policy", { workspace, viewer }),
1154 setPolicy: (workspace, viewer, policy) => call("set_policy", { workspace, viewer, policy }),
1155 installRequests: (workspace, viewer) => call("install_requests", { workspace, viewer }),
1156 requestInstall: (workspace, viewer, listing, note) => call("request_install", { workspace, viewer, listing, note: note ?? null }),
1157 resolveInstallRequest: (workspace, viewer, id, status) => call("resolve_install_request", { workspace, viewer, id, status }),
1158 marketplaces: (workspace, viewer) => call("marketplaces", { workspace, viewer }),
1159 addMarketplace: (workspace, viewer, address, name) => call("add_marketplace", { workspace, viewer, address, name: name ?? null }),
1160 removeMarketplace: (workspace, viewer, name) => call("remove_marketplace", { workspace, viewer, name }),
1161 refreshMarketplace: (workspace, viewer, name) => call("refresh_marketplace", { workspace, viewer, name }),
1162 discover: (workspace, viewer) => call("discover", { workspace, viewer }),
1163 plugin: (workspace, viewer, ref) => call("plugin", { workspace, viewer, ref }),
1164 pluginInstalls: (workspace, viewer) => call("plugin_installs", { workspace, viewer }),
1165 installPlugin: (workspace, viewer, ref) => call("install_plugin", { workspace, viewer, ref }),
1166 setPluginEnabled: (workspace, viewer, ref, enabled) => call("set_plugin_enabled", { workspace, viewer, ref, enabled }),
1167 uninstallPlugin: (workspace, viewer, ref) => call("uninstall_plugin", { workspace, viewer, ref }),
1168 updatePlugin: (workspace, viewer, ref) => call("update_plugin", { workspace, viewer, ref }),
1169 pluginAgents: (workspace, viewer) => call("plugin_agents", { workspace, viewer }),
1170 connectors: (workspace, viewer) => call("connectors", { workspace, viewer }),
1171 connector: (workspace, viewer, id) => call("connector", { workspace, viewer, id }),
1172 addConnector: (workspace, viewer, input) => call("add_connector", { workspace, viewer, input }),
1173 setConnectorKey: (workspace, viewer, id, headerName, value) => call("set_connector_key", { workspace, viewer, id, header_name: headerName, value }),
1174 removeConnector: (workspace, viewer, id) => call("remove_connector", { workspace, viewer, id }),
1175 refreshConnector: (workspace, viewer, id) => call("refresh_connector", { workspace, viewer, id }),
1176 startConnectorSignIn: (workspace, viewer, id, redirectUri) => call("start_connector_sign_in", { workspace, viewer, id, redirect_uri: redirectUri }),
1177 finishConnectorSignIn: (workspace, viewer, state, code) => call("finish_connector_sign_in", { workspace, viewer, state, code }),
1178 signOutConnector: (workspace, viewer, id) => call("sign_out_connector", { workspace, viewer, id }),
1179 grantConnector: (workspace, viewer, id, scope, target) => call("grant_connector", { workspace, viewer, id, scope, target }),
1180 revokeConnector: (workspace, viewer, id, grant) => call("revoke_connector", { workspace, viewer, id, grant }),
1181 agentConnectors: (workspace, handle, viewer) => call("agent_connectors", { workspace, handle, viewer }),
1182 customizeBundle: (workspace, viewer) => call("customize_bundle", { workspace, viewer }),
1183 };
1184}