13 June 2026 10min read

Keeping Up With Swift Forums Using Codex

The most interesting AI workflow I have right now is not a coding workflow. It has code in it. It has a small Swift CLI, some auth state, a few JSON exports, a Codex automation, and way too much knowledge about how Discourse represents unread things. But it is not one of those fancy loops that will make you a product overnight.

Instead, it is something much more useful and real. A smart automation that covers a part of my life I have not had time to keep up with for a while, reading the Swift Forums.

I like Swift Forums. I want to keep up with it. But long gone are the days when I had enough time to constantly check it, open it every day, and perform a tiny archaeology exercise to understand what I have seen, what I have not seen, what is new, what is only a notification, what is a topic I subscribed to months ago, and what the little number on my avatar is trying to emotionally communicate.

This sounds like a small problem, but you need to understand that I care deeply about these forums, and I still love the Swift language and its community. So if AI can help me keep that part of my life alive, let’s use it!

This works because of Codex Automations

The important piece here is Codex Automations.

Without automations, this would still be useful, but it would be another thing I have to remember to run. That already ruins the whole point. The reason this works in my life is that Codex wakes up every morning in the same thread and does the catch-up for me.

More specifically, it works because this is a heartbeat automation. It does not create a new conversation every morning, which it did for a while and I hated having to manage the threads, inbox zero please! It comes back to the same thread, which means the previous forum conversations are still there, and I can keep referring to them naturally.

Normally I would be worried about context rot with a thread that keeps growing forever, but Codex auto-compaction is good enough that I mostly do not have to think about it. The old details get compressed, the important shape remains, and Codex memory gives the workflow another durable layer for the policies that matter.

The important part is that this is not a script that runs somewhere and sends me a static report. It is not a cron job that calls an LLM at the end to make the output prettier. It is an AI agent that wakes up, decides what data it needs, calls the tools, reads the results, follows the policy we have refined together, and writes the report back into the conversation.

That distinction is the part I care about.

AI Driven Design

There are two ways to build something like this.

The common one is program first.

That is a perfectly reasonable architecture. I have built many things like that. The program owns the workflow, and the model is a feature inside that workflow.

But over time I’ve experimented with the opposite, and I’ve started to like it more.

Side by side comparison showing a program-driven flow where the deterministic program owns orchestration and calls AI as one step, next to an AI-driven flow where Codex owns orchestration and calls deterministic programs as tools

The AI owns the workflow. The classic program is there to expose reliable verbs.

I do not see people talk about this distinction enough. The docs usually talk about tool use, function calling, or the agentic loop, which is all true. But for me the key design question is simpler. Who is driving?

If the program drives, the AI is a component.

If the agent drives, the program becomes an instrument.

That second shape feels much nicer for personal workflows in the age of AI. Not because it is magically better. It brings its own problems. The agent can make different decisions. It can misunderstand a queue. It can forget a policy unless the prompt and memory are good. It can confidently do the almost-right thing.

But those are the right problems to discover and solve.

Because if the workflow lives in the agent, I can correct it in the same place where I consume the result. I can say “no, notifications should be newest first”, or “when a proposal is already implemented, tell me that”, or “do not mark a topic read unless it appeared in this run”. The automation changes by changing the conversation, the prompt, and the tools around it. The workflow builds and evolves itself.

That is the design space I want to explore more.

Determinism Moves To The Edges

The first naive version was simple:

Summarize the next unread Swift Forums topics for me.

That sounds like one queue.

It was not one queue.

There were new and unread topics from the forum UI. There were subscribed topics that had accumulated in the background. There were notifications on the profile avatar. There were topics that my local automation had already summarized, but that Discourse still considered unread because we had not written that exact read state back to the forum.

This is where the agent started failing too often.

Not because the model is bad, but because the world around it was surprisingly complicated. Discourse has its own model. I have my own requirements. The unread page, the avatar badge, subscribed topics, read state, and local progress are related, but they are not the same thing.

If every run lets the AI rediscover that whole world from scratch, every run can be a little different.

So the solution was not to remove the agent from the workflow. The solution was to move determinism to the resource-gathering side.

That is why the Swift CLI exists.

The CLI knows how to talk to Discourse. It knows which endpoint represents which queue. It knows how to decode the data, sort it, compare it with local progress, and expose the result in a shape Codex can reason about.

From the agent’s point of view, the tool looks roughly like this:

swiftforums

Commands:
  export-new-unread              Export forum topics marked new or unread.
  export-priority-notifications  Export notifications behind the avatar badge.
  export-pending-subscribed      Export subscribed topics not yet summarized.
  export-topic --id <id>         Export one topic with posts and metadata.
  progress set <id> ...          Record local summary progress.
  mark-read --topic <id>         Mark one exact topic as read.
  mark-seen --notification <id>  Advance seen notification state.
  auth                           Refresh browser and API authentication.

The agent does not need an open-ended “go browse the forum and figure it out” instruction. It gets a small language. Export this queue. Export this topic. Record this summary. Mark exactly this topic read. Mark exactly this notification seen.

The AI is still in charge. It still decides what to call, how to interpret the result, what deserves a longer explanation, and what to include in the final report. But it is no longer guessing where the data lives.

That makes the prompt much more concrete too. The real one is longer, but the shape is this:

Every morning, catch me up on Swift Forums.

1. Export new and unread topics.
2. Export priority notifications from the avatar badge.
3. Export a small batch from the subscribed backlog.
4. For each topic you include, fetch the topic details.
5. Summarize the discussion, not just the title.
6. Investigate context when useful:
   - Is the author someone from the Swift Core team or Working Groups?
   - Is there a related Swift Evolution proposal?
   - Has the proposal already shipped or become outdated?
   - Is this from someone I explicitly follow?
7. Mark only the exact topics and notifications you handled as read or seen.
8. Explain anything surprising about the counts.

That is the real contract.

The CLI makes the world legible. The prompt tells the agent what “done” means. Codex performs the workflow.

Read State Matters

At first I thought the automation could have its own local progress file and that would be enough. It would know what it had summarized, and it could skip that next time. But that creates a weird split reality.

The automation thinks I am caught up, but Swift Forums still shows unread topics. Or I read something manually in the forum, but the automation still thinks it is pending. Or the avatar badge keeps shouting a number that no longer matches what I believe happened.

That is not good. I still want to visit Swift Forums myself sometimes. If I have a break and want to catch up manually, I should be able to do that. The automation should not trap me in its own private version of reality.

So the CLI can mark topics read and notifications seen, but only as part of the same run that reported them.

That constraint matters more than it sounds. Earlier versions could say, more or less, “mark everything I have summarized locally as read”. That was too broad. It mixed today’s report with old local progress, and it made it too easy for the automation to change forum state that I had not just reviewed.

The current version is much narrower. If a topic appears in today’s report, Codex can mark that topic read. If a notification appears in today’s report, Codex can mark that notification seen. Nothing else moves.

That keeps the forum and the automation synced without letting the automation quietly clean up a larger backlog behind my back.

Authentication Is Where Reality Leaks In

The annoying part was authentication.

Of course it was.

The workflow uses a mix of browser state and API calls. Some things are easier to get from the forum API. Some things require the logged-in browser session. Sometimes the browser automation works. Sometimes the session expires. Sometimes the agentic browser thinks it is logged in, but a probe says the API is not. At one point there was a socket path that was too long because a local session name made a Unix path exceed the limit.

So yeah, a big pain in the a**.

But it is exactly the kind of thing that decides whether an automation becomes useful or remains a demo.

The command I want to exist from the outside is boring:

./tools/swiftforums auth

The amount of work hidden behind that boring command is not the point of the post, but it matters. If the agent cannot reliably get into the real product, the workflow is fake. If the auth flow requires me to babysit it every week, the automation is fake in a different way.

This is also why I like having the auth as part of the same tool boundary. Codex can notice when an export failed because auth expired, refresh the session, and try again. The agent drives, but the scary part is still wrapped in a specific command.

And now, this has been running for weeks without tripping over auth. :)

What I Get Every Morning

With those pieces in place, the morning report is finally useful.

Codex wakes up in the same thread and gives me a catch-up across the queues of pending threads. Not just a forum summary, but an AI-improved version of it. It can check why a thread might be relevant, whether the topic connects to a Swift Evolution proposal, whether the proposal is already implemented or outdated, and who is participating in the conversation.

This matters because “new” is not one thing.

An unread topic means “you have not read this”. A notification means “someone or something explicitly touched your attention”. A subscribed backlog item means “you once cared about this, and maybe you still do”.

Those are all different and need my attention differently. The report can respect that because the agent is not just summarizing text. It knows which lane the topic came from and why it was included.

The Conversation Became The Control Panel

This is the part that makes the AI-driven version better than a normal program that calls an LLM.

Everything lives in a Codex thread. From the CLI call results to the summaries.

That means that while I am reading the summaries, I already have the full power of the agent next to them. If a topic is interesting, I can ask Codex to go deeper. If something sounds important, I can pull on that thread immediately.

And when a topic deserves a different kind of attention, I can move it. I can use the Codex handoff workflow to send the learning into a new thread, or into the context I use for my Obsidian vault, without losing the reason it mattered in the first place.

A report can tell me what happened, but more than that is hard to get. Instead a conversation can help me keep learning, which is what I care about the most.

This Is The Useful Part

Thanks to this I am keeping up with the Swift community again. Not perfectly. Not with some magical autonomous system that I blindly trust. But enough that I wake up and have a path back into conversations I was slowly losing.

That has a real impact on my day to day.

I keep learning. I notice proposals. I recognize people. I can follow threads that I would have missed. I can ask better questions because the context is already there. And I can still open the forum myself because the automation is synced with the same real state.

That is what I want from AI.

Not a black box that takes a piece of my life away from me, but a legible system that helps me stay connected to the things I care about.

If you enjoyed this post

Continue reading