Sign in
AI InsightsJun 01, 20265 min read

Inside our "what-shipped" workspace

Cory Waddingham
Cory Waddingham

The "what-shipped" workspace is one of the most boring things we run. It looks at our GitHub merges and writes them up. Once a day for an internal audience and once a week for our developer community. That's it, that's the product.

It is also the workspace I would point a curious developer at first, because the things it does well are things you would otherwise hold together with cron, a secret, and a small Python file you stop maintaining six months in. Watching it run is a good way to see what the platform is actually for.

Three audiences, one source of truth

GitHub knows what shipped. The question is who else needs to know.

Three groups, in our case. Marketing and GTM need a clear picture of what is user-visible so they can plan announcements, content, and customer outreach. Engineering leadership needs to stay aware of which issues are closing out without keeping a GitHub tab pinned all day. And our Artisan community wants the weekly view of what is actually moving in the product.

None of those audiences want to read raw commit logs. Marketing especially does not need read access to every repo in the org to do their job. That kind of standing access is awkward to grant, awkward to audit, and the wrong shape for what people actually need, which is the digest, not the source.

What the workspace does

To start, there is one agent. It is an LLM agent that uses Guild's built-in GitHub tools to pull merged PRs over a configurable window. Daily uses 24 hours. Weekly uses 168. The same agent serves both. The window is passed in by the trigger.

The workspace context tells the agent the things that do not change run to run: the repos we care about, who the audience is for each cadence, what tone to use, what to emphasize and what to skip. When we want to change behavior, we edit prose, not code.

Trigger one fires daily and writes its output to a Session. Trigger two fires weekly and does the same.

That was version one. And it worked well enough. The people who needed the digest went into Guild and read the Session. Engineering leadership got their daily view. Marketing got their weekly update. The Artisan-facing weekly summary got copied out by hand and posted to our community channel.

The hand-copy step was the annoying part.

The change that fixed it

I added one sentence to the agent's prompt:

Once this is collected send a DM via the slack agent in this workspace to the 'what-shipped' channel with the output.

That was the whole change. Worth slowing down on what is doing the work in that sentence, because the size of the diff hides the size of the result.

"The slack agent in this workspace" is a natural-language reference that the LLM resolves against the agents already installed in the workspace, which includes a Slack agent. The model finds it and uses it. No agent ID, no import, no wiring. The channel name, "what-shipped", is data, passed inline.

When the Slack agent runs, it uses our org-level Slack credential, the one we connected once at Settings →  Credentials. The "what-shipped" workspace never had Slack credentials of its own, because in Guild it does not need them. Credentials live at the organization level and any agent that needs them gets them at runtime.

Nothing in the trigger config changed. Nothing in the agent's tool list changed. No package was added. No code was deployed. A weekly report that someone used to load and copy out by hand turned into an automatic delivery, by editing one sentence of prose.

Why this works

A few things have to be true for that one-sentence change to do what it did, and they are worth pulling out one at a time because each one is a deliberate platform choice.

The orchestrating agent is an LLM agent. Coded agents in Guild are deterministic and ideal for fixed workflows where you want behavior and cost to be identical every run. An LLM agent is the right shape when you expect the workflow to evolve in plain English over its lifetime. This is that case. The weekly digest started as a report-to-Session and turned into a report-to-Slack, and it might turn into a report-to-Confluence next. The fact that the agent can pick up new behavior from a prompt edit is the whole reason a prompt edit was sufficient.

Credentials are central. Connecting GitHub once at the org level means every workspace, every agent, every Session that needs GitHub gets it. Same for Slack. The marketing team member reading the digest in Slack has never seen a token, a repo URL they should not see, or anything that resembles auth. Their access to the information is exactly the surface area they need: the channel.

That matters for access control more than I want to belabor. Granting standing GitHub read access to a non-engineering team to support a weekly digest is the kind of thing that is easy to set up and hard to walk back. Granting them membership in a Slack channel is normal. The digest becomes the access boundary, not the underlying source.

Agents in a workspace are discoverable. The Slack agent was already installed because we use it for other things. The what-shipped agent did not need to know about it ahead of time. The LLM finds installed agents at runtime and uses them when the prompt asks for them. This is the part of the platform that makes the atomic-plus-orchestrator pattern actually pleasant. You install the small, single-purpose agents (a Slack-DM agent, a Confluence-page agent, a Jira-comment agent) into the workspace, and your orchestrating agent reaches for them by name in plain English.

Every run is a Session. We can pull up any daily or weekly digest from any point in the past and see what the agent did, what it pulled, what it wrote, what the LLM decided. For an internal digest this is a nice retrospective tool. For something with stricter requirements it is an audit trail with no extra work.

The alternate-universe version

Take the same workflow and build it without Guild. You write a script. The script needs a GitHub token, so you stand up a PAT and decide where to keep it. You add it to a secrets manager, or you put it in env vars and hope. You write the GitHub fetch, the summarization (so now you are managing an LLM provider key too), the formatting. You set up cron, or a GitHub Action, or a small worker. It runs. Good.

Three months later you decide you want the weekly version to go to Slack instead of an inbox. You add a Slack incoming webhook. You decide where that lives. You plumb it through env. You write the post step. You redeploy. Someone has to maintain all of that. Six months later the PAT rotates and the script silently stops working until a human notices the digest has not shown up.

In our version, the Slack change was a sentence. The credential rotation story is "go to Settings and reconnect," and every consumer is fixed.

I am not making the case that you cannot build this without a platform. Obviously, you can. The question is, what does the platform take off your plate? For a workflow this small, the answer is more than I would have guessed before I worked on it.

What's next

A few directions we are looking at:

Github Issue enrichment, so the digest can include ticket context alongside the raw PR list. The org-level credentials are already there, which means the same prompt-edit pattern applies.

An on-demand variant triggered by a Slack mention, so anyone can ask "what shipped this week" in the channel and get the digest fresh. That is a webhook trigger on the existing agent.

And finally, a Google Doc auto-generated off the weekly run, for the version of the audience that lives in docs instead of Slack.

If you want to build something like this in your own workspace, the pattern is a good starting point. Install the GitHub integration, give the agent the repos in your workspace context, set up a time trigger, and start with output-to-Session. When you want the output somewhere else, write a sentence.

One control plane.
The complete agent lifecycle.
Get a working agent in under 10 minutes.
No credit card required.