Browse documentation
Docs/Language

Teams and processes

A PROCESS describes how several participants work on something together: who is asked what, what each of them may see, and when the work stops. A TEAM names who fills each role. Ordinary…

Teams and processes

A PROCESS describes how several participants work on something together: who is asked what, what each of them may see, and when the work stops. A TEAM names who fills each role. Ordinary Grid formulas still do the calculating; a process only coordinates requests to people, models or agents.

# Each role uses a saved profile; these profiles have no tools.
TEAM panel
  advocate USING "debate-advocate"
  challenger USING "debate-challenger"
  chair USING "debate-chair"
END

# Both sides open each round independently, then the chair guides.
PROCESS debate(topic, evidence) WITH advocate, challenger, chair
  SHARE topic, evidence WITH advocate, challenger, chair

  REPEAT UP TO 3
    INDEPENDENTLY
      supporting = ASK(advocate, "Make the case for, addressing prior chair guidance.")
      opposing = ASK(challenger, "Make the case against, addressing prior chair guidance.")
    END

    SHARE supporting, opposing
    direction = ASK(chair, "Assess the arguments and guide or conclude the debate.") EXPECT {
      action: "continue" | "conclude" | "unresolved",
      assessment: string,
      focus: string
    }

    SHARE direction

    YIELD direction UNTIL direction.action != "continue"
  END
END

topic = "Should the library open on Sundays?"
evidence = [
  "The fictional library has a fixed weekly staffing allowance.",
  "Some patrons cannot visit during weekday opening hours.",
  "No estimate of Sunday demand has been supplied."
]

# Building the plan spends nothing; a person starts the run.
proposal = debate(topic, evidence) USING panel

Writing debate(...) USING panel builds a plan; it does not start anything. Each ASK here uses one model call, so this debate makes at most nine. A person starts the run from the Process surface, and the run is recorded.

Teams and processes

What each statement does:

  • ASK(role, question) continues that participant's conversation and binds their answer. EXPECT { ... } asks for structured data in that shape and rejects an answer that does not fit before any later work runs.
  • ASK(FRESH role, ...) starts a fresh conversation for that participant.
  • SHARE x WITH role gives the named values to those participants for their later turns. Without WITH, everyone in the process sees them. Nothing else a role said or saw is shared.
  • UNSHARE x WITH role takes the value out of that participant's future context; what they already answered stays.
  • INDEPENDENTLY ... END asks the enclosed turns without letting any of them see the others' answers.
  • REPEAT UP TO n ... YIELD value UNTIL condition END repeats at most n times; YIELD names what each round produces and UNTIL says when to stop.
  • condition THEN expression ELSE expression runs only the selected branch.
  • RUN child(...) USING role = other runs another process inside this run, with fresh conversations for its participants.

TEAM, PROCESS, POPULATION and ROOM start a declaration only with their full header, so the same words remain ordinary names elsewhere, as in process depends_on api.

Process values can use the total built-in functions, such as NOT, ISBLANK, SUMPRODUCT, COUNT and AVERAGE. Handle an error inside the expression that produced it with IFERROR or TRY ... THEN ... ELSE, for example safe = TRY total / count ELSE 0. An error that is not handled stops the run where it is first used, before any later work.

A process can let a role read one of the model's views with SHARE VIEW Board WITH reviewer, or also run its actions with ... TO ACT. The person starting the run decides which views the plan may share, and can grant a view for reading only.

Status: supported on Desktop, where processes run one step at a time. Other hosts must be selected explicitly.

Populations

A POPULATION turns a list into a group of participants, each with a stable key and optional private data:

# Each member's key, profile and private data.
POPULATION audience FOR person IN [
  {key: "north", priority: "Keep the river clean"},
  {key: "south", priority: "Plant more trees"}
]
  person.key USING "reader" WITH person
END

TEAM panel
  readers USING audience
END

PROCESS consult(topic) WITH readers
  EACH reader IN readers
    ASK(reader, topic)
  END
END

report = consult("What should our town improve first, and why?") USING panel
  • Membership is frozen when the run starts. Later changes to the list do not change who takes part.
  • EACH member IN group visits members in order and returns {key, value} rows, or folds them with WITH. A later traversal continues each member's own conversation.
  • INDEPENDENTLY EACH gives each member a fresh conversation for that traversal.
  • An empty population asks nobody, and a fold returns its starting value.
  • SHARE and UNSHARE can address the whole group or one member.
  • Members stay inside their traversal. They cannot be stored as ordinary values.

A population imported from a .gs library may build its membership from that library's own constants.

Status: supported, with members running one at a time. Rooms for populations and published reads in imported populations are not available yet.

Collecting and matching

Two further forms are recognized, formatted and type-checked, but are not yet a supported product feature:

  • INDEPENDENTLY EACH item IN items COLLECT ALL or COLLECT k gathers results as members finish. It returns {values, outcomes, enough}, where each outcome records whether that member finished, failed or was not needed. k must be between 1 and 32 and no larger than the group.
  • A process MATCH may start an arm with a step such as RUN or ASK. It must cover every case, its arms must produce one type, and names bound in an arm are visible only inside that arm.

Status: recognized and checked only. Do not rely on these forms in production processes yet.

Further reading