← newsletter

Agentics: How we use Nori to not touch X

Wouldn’t touch it with a 10 foot pole … I will with an agent, though

Gaurav Thakur · August 25, 2026

Guest post collab with Gaurav, my GTM Intern at Nori.


Fortunately, if you’re trying to learn more about the AI world, there’s a plethora of online communities you can go to and learn from people who are operating at the edge and want to share their learnings. X generally has the ai-pilled users that either make you believe the world will end tomorrow or we will cure cancer tomorrow. Substack generally has the users that are ai-rejectors and value human content. And LinkedIn … LinkedIn is a lost cause. Now, of course, it’s great that there are distinct communities you can join, but unfortunately, this also means communities are dispersed, and, if you create content like we do, then you will find it distinctly tedious syncing your work across these different platforms.

Much of the company’s work gets posted to Amol’s Substack to get more eyeballs on what we’re doing. But this also means we’re totally missing out on the X communities, and none of us have the time to constantly monitor an X account, and frankly don’t want to spend much time on X. So we did what any logical person would do. We used Nori.

Nori is a cloud agent. Cloud agents are just coding agents that live in an isolated cloud environment, not your local machine. This is useful to have your agents run in the background, so you can delegate a task and leave. The agent continues without your laptop or terminal remaining open, then returns an artifact such as an analysis, code change, or pull request. It can be started by a person in Slack from your computer or phone, or automatically by a trigger. A huge benefit of cloud/background agents, which we will talk about here, is that they (along with their cloud environment) can be fired upon set triggers, whether they be event-reactive or time-based.

The benefit of using coding agents rather than just a deterministic pipeline for this task is that by having agents as the couriers of content and having them scrape the timelines, you avoid a lot of the judgment problems that deterministic pipelines can’t handle. In trying to account for every edge case in a brittle workflow, this project would easily be turned from a one-day thing into a multi-week project. Because the agents can exercise judgement, they do a pretty good job at handling edge cases and working around blockades without human intervention.

Now, X and Substack have similar types of posts: X has regular tweets and long articles, Substack has notes and posts, these are their respective equivalents. Both of these workflows, though, are just Nori Sessions cron triggers stored in a broker database.

Notes and tweets

Let’s first start with notes/tweets. Amol usually posts notes directly to Substack throughout the day at the time he has a thought worth posting. So, we have a Nori cron trigger for every 3 hours, so that at time of trigger, a fresh cloud session gets spun up. This cron trigger is stored in our broker database (a control-plane database that manages Nori Sessions which includes cloud runtime allocations, scheduled triggers, session resumability, etc.) Note that session Micro Virtual Machines (micro VMs) are ephemeral, so they’re released when the session ends. But the broker isn’t. Its SQLite database holds trigger definitions and run history on disk, so a schedule set today still fires next week on a machine that doesn’t exist yet.

So, at every 3rd hour, the broker claims a micro VM from a fleet and injects a stored prompt explaining that the agent was kicked off from a trigger, what it must do plus necessary steps, and that there is no human present so it must finish its task in one turn. The agent is also initialized with the following tools: nori-substack (read public Substack notes and convert them into structured JSON), nori-slack (access to the Slack Web API, scoped by the broker proxy to the thread that spawned the session), and nori-twitter (to access X).

After the session is fired up with the proper provisioning, the agent first loads a ledger (a Google Sheet) that holds all of the Substack notes that are already posted on X, so the agent can cross-check to avoid posting duplicates. Now although Amol posts his notes/articles to Substack directly, we all want to manage the company’s X account from Slack (this is where the team interacts with the agent). So during each session, the agent will scrape Substack up to 4 hours prior (extra hour for overlap in case of late/slow runs) but may widen to 24 hours if a prior run failed. It’ll then cross-check with the ledger and all non-overlaps will then get sent into Slack for approval. Once someone approves, denies, or makes changes to the draft, the post will then go out during the subsequent session when the agent scrapes Slack for approvals.

So the flow looks like this:

  1. Every 3 hours, the broker claims a microVM from the fleet and starts a fresh agent, with proper provisions
  2. Scrape Slack for older proposals from the past 7 days
  3. If approved, connect to X and post a 1-1 version
  4. Reply in the original Slack thread with a link to the new post and append the post to the ledger with note ID, date, link
  5. Scrape Substack for new notes (4-24hr window)
  6. Filter notes down (drop duplicates from the ledger and anything confirmed live in Slack) and send proposals into Slack
  7. Tear down the session, no keys or memory are kept on the box, and the agent goes back to agentlandia, all without me needing to monitor or guide it
Agent J from Men in Black holding up a neuralyzer
This is basically what happens to all our agents when the session is done

A small note I want to make here from previous trial and error. For the Slack proposals, anyone can either confirm, deny, or make an edit. If they decide to make an edit, then the agent will echo that edited post back to Slack and wait for another confirmation. This is because sometimes the agent can misinterpret the edit, so it needs another look. Also, the agent needs a strict “approve” or “deny” to mitigate any misinterpretation.

Articles

Now for syncing articles. To start, writing tweets and publishing articles are distinct actions in X’s own product model, and an article is just a much bigger swing in general than a tweet. So this agent leaves articles as draft only. Also posting articles is just very finicky for agents, hence the precaution. The process for posting articles is quite similar to posting notes, with some differences, though. One is that there is no ledger for checking duplicates for articles. Instead, the agent goes through all article drafts and published articles on X and dedups based on titles; the title can act as the article’s “key” (I’m not gonna post two articles w/ the same title). But for standard tweets, it’s much more tedious to dedup by scraping X, so we have the agent just import all tweets to the Google Sheet and give each tweet its own ID. So after deduping, the agent exports a platform-neutral article by removing all Substack specific features (subscription widgets, forms, buttons, etc) while preserving more integral things like paragraphs, lists, headings, blockquotes. The output is then versioned JSON. The agent inserts this article into x.com/compose/articles using the following flow: Write → fill title → put HTML and plain text on the clipboard and paste → for each image, delete the marker and run X’s own insert media feature. Now after all this, we have a little dilemma to save the article. The articles composer has no save button; the only way to save a draft is autosave, which fires when a change is made to the draft. The problem here is that most of what the Command-Line Interface (CLI) just did doesn’t look like typing because it’s just copy pasting and inserting images. So the agent will touch a field that X definitely watches like altering the title, and then revert it to the original. After the draft is saved, the agent posts it into Slack as “ready to review” with a link to the draft, and in two swift clicks I post the X article while sipping piña coladas on a beach in Central America (my desk in a co-working space).

Something to note here, highlighted code blocks don’t import to X’s article editor cleanly, but, thankfully, we don’t really write code anymore, so you won’t be seeing it in any articles.

And that’s it for posting articles and tweets! But, we’re still missing replies…

Replies

Apparently with the X algo, if you are a small account, you can farm views by commenting on posts by people with a lot of followers. Do enough of these while also posting regularly and you’ll start getting more views on your posts. More than if you didn’t comment at all and only posted, at least. But, as mentioned before, nobody here wants to scroll X, so the agent scrapes X and feeds a couple posts a day that we should comment on. When we first started the account, Amol gave the agent a couple of people that he enjoys listening to, and the agent followed their X accounts and similar accounts, so the feed is already kind of curated. This is set up as a trigger, so every evening, the agents send a message in Slack with 3 posts that we’d find interesting. Someone from the team makes the comments in the same thread, the agent posts them to X, and the account … still somehow only has 12 followers (4 of them are fake women, 3 of them are Amol, Cliff and me). Thank you to our 7 followers, though! This trigger also gives us new activity (new followers, people mentioning the account, and replies), but, sadly, there’s not much new activity … (go follow @noriagent)

Now, with cloud agents, we can syndicate Substack to X all largely through Slack. Nobody has to watch an agent work or worry about it posting some heinous stuff to the accounts and we can sleep peacefully knowing that, as our dev Ritam once said:

Slack message from Ritam telling Amol not to put this on Substack
hey, he didn’t say “Gaurav” can’t post it