# When I Narrowed My Human Inputs Down to Just Todoist and Discord, the System Started Running Itself

> Source: <https://dev.to/ebibibi/when-i-narrowed-my-human-inputs-down-to-just-todoist-and-discord-the-system-started-running-itself-51lf>
> Published: 2026-08-15 12:32:48+00:00

*Originally published on my Substack. I'm a Microsoft MVP based in Japan, writing in English about the AI agent systems I actually run in production.*

AI tools have multiplied. So have agents, skills, and automation scripts.

And yet, somehow, my hands are never free. I wake up, open a dashboard, check notifications, go look at the logs for a failed job, and think, "wait, where was that process even running?" Every time I add one more automation, I add one more place I have to go check.

That was me, up until last year.

The cause was clear: **I kept thinking about what to have AI do, and never once designed where I myself would touch things.** So I rewrote my policy down to one line. There are only two things a human does: throw tasks into one place, and have conversations in one place. No other entry points get added.

🤖✍️ This article was co-written with AI — an AI agent (Claude Code) generated the draft automatically based on real collaborative work with Ebisuda, who then reviewed and revised it before publishing.

In this series, I share the systems I've actually built using AI as case studies — including both the ones that worked and the ones that failed.

What I set out to build wasn't a specific tool or a specific agent. It was **the design of the surface humans touch.**

The rule I settled on was just two lines.

The only human entry points are **Todoist** (for dropping in things to do) and **Discord** (for conversation)

Everything else gets pushed to the AI and scheduler side

This is the opposite of "let's have AI do a ton of work." When people try to maximize what AI can do, they end up adding more tools. More tools means more settings screens, more places logs pile up, more places you have to go check "how's it doing now." Left unchecked, the number of automated processes and the number of places a human has to go look both grow together.

So the thing I needed to decide first wasn't the scope of AI's work — it was **the footprint on the human side.** If you fix that footprint first, whatever overflows has nowhere to go but onto the AI side. It's a strategy of turning the design from "addition" into "displacement."

Once you actually try it, you find that reducing entry points is much harder than reducing features. There are three reasons.

Start using a new service, and you gain one more UI for that service. Write one automation, and you gain its config file plus the logs you check when it fails. Add monitoring, and you gain a monitoring dashboard.

Each of these is, individually, the right call. Nobody sets out thinking "let's add another entry point." And yet they keep adding up. That's because **the growth in entry points happens outside the scope of any single decision.** By the time you notice, your morning check-in has gone from ten minutes to thirty.

Say you have a process that's ninety percent automated, with the remaining ten percent needing a final human check. That's a common design, and not a bad one.

The problem is that for the sake of that ten percent, **you still have to keep opening that tool.** Even though the actual work time has dropped by ninety percent, the amount of mental real estate it occupies barely shrinks. That nagging "wait, I haven't checked that today" feeling is proportional to the number of entry points, not the amount of work. Raise the automation rate all you want — as long as the entry point remains, the perceived burden doesn't go down.

Features grow when you add them, so adding is a task you can just do. Entry points are different — **there's no such thing as a task that reduces them.** All you can do is take the roundabout path: decide "starting today, I won't go check this tool's UI," and then build the wiring to funnel that information somewhere else instead.

What's more, while you're building that wiring, entry points temporarily increase, because both the old route and the new route are alive at once. If you run out of steam at this stage, you end up simply having added one more entry point. I've done this more than once.

The policy is simple. Narrow it down to two entry points. Saying it takes three seconds.

But when you actually try to do it, some questions remain that you can't take a single step past without answering.

**Where does everything you cut go?** Closing an entry point doesn't make the information you used to see there disappear. Failure notifications, deadlines, pending approvals — they all need somewhere to go. Close an entry point without preparing a destination, and that's not automation; it's just choosing not to look.

**What becomes invisible when you close an entry point?** And how do you notice that it's become invisible? I actually caused an incident here. There was a stretch of time when I assumed a process was running, and it had quietly stopped.

**Is "two" even enough to begin with?** There will inevitably come a moment when it isn't. Do you add another one then, or hold the line? Without a clear criterion, you slide back into three, then four, without ever deciding to.

From here on, I'll write about the actual results of running this design, counting up everything the records show. How many processes are currently running automatically, how many times a day they execute, and how many of those runs fail. What broke as the price of narrowing down to two entry points, and how I fixed it. And, in the end, what I had to give up to hold the line at "two."

__ *

The "two entry points" design described in this article doesn't run on philosophy alone. Only once AI can recall on its own which project is being discussed, and can execute fixed procedures at the same quality every time, does it become possible to shrink the surface humans touch. The foundation for that is Ebi Workspace (formerly Ebi Workspace (formerly claude-workspace)). Project management, context recovery, the skill execution framework — every mechanism that appears in this article runs on top of this plugin.

[I sell the actual Claude Code setup I use, packaged as a plugin.]

This is the execution framework that connects Claude Code and Codex through Discord as the front door, letting multiple AI agents converse, hand off work, and coordinate with each other.

👉 [Ebi Agent Chat Relay — Supporting Conversation and Coordination Across Multiple AIs](https://github.com/ebibibi/claude-code-discord-bridge)

__ *

__ *

Here's the overall picture first. Humans touch only the two items at the top; in principle, the three below are never checked directly.

All the numbers below are actual measurements I counted on August 5, 2026, the day I wrote this article. They aren't drawn from memory or from design documents — I counted them directly from config files and databases.

Anything I think of, anything I'm asked to do, anything with a deadline — it all goes straight into Todoist. I don't categorize it, and I don't assign it to a project. I just drop it in.

The reason I don't need to categorize is that **Todoist isn't the source of truth.** The source of truth for tasks lives in each project's note in Obsidian; Todoist is used purely as an intake tray for the entry point. A morning job picks up whatever's been dropped in and writes it out to Obsidian, and anything with a deadline gets aggregated into a deadline dashboard.

This was my first design decision. **An entry point must never be a "place to organize things."** The moment you demand organization, it becomes a chore, and any entry point that becomes a chore will inevitably be neglected. The only job an entry point is allowed to do is receive.

The other entry point is Discord. This has effectively become my entire working environment.

My self-built OSS project, Ebi Agent Relay Chat (formerly known as claude-code-discord-bridge), maps Discord threads and Claude Code sessions one-to-one. Start a thread, and one session spins up; reply in that thread, and the same session continues. Even from the Discord app on my phone, I get a fully-featured Claude Code.

When I actually measured it, across the 33 days since July 3rd — when session records began — **557 sessions** had been started (541 in just the last 30 days). That's roughly 17 a day. And interestingly, of the 557 recorded sessions, **every single one had "discord" as its origin.** I no longer start Claude Code by opening a terminal.

The backend breakdown also came out: 219 on Claude, 67 on Codex, and 271 from before records began. Since I can switch AI per thread, I use Claude for implementation and Codex for review, and that split happens entirely within the same single entry point. **Narrowing to one entry point doesn't mean narrowing to one AI.**

Claude Code is what executes the instructions that come in through the entry points. On top of it, I've been building up "skills" — repeated tasks solidified into procedures.

The actual count is **130.** Of those, **124 are ones I built myself** , and the remaining 6 are links to external repositories. Fetching the weather, generating invoices, building slides, promoting articles, finishing off video metadata — once I've done a task once, I make sure it can be called as a skill from then on.

Skills matter not because they add capability, but because **they lower the pressure on the entry points.** A task without a fixed procedure requires the human to remember "how did I do this again" every single time, and remembering means opening documents or tools — in other words, adding an entry point. Turning something into a skill is also, in effect, closing off one entry point.

Processes that run without any human instruction are pushed onto my self-built scheduler. This is a domain governed by a written rule: "don't use cron" (I'll get to the story of how this declaration was, in practice, not fully upheld, later on).

Counting the config files: **196 job definitions** (118 of them active), and **249 schedule definitions** (183 of them active). Cross-referencing active schedules against active jobs, **114 jobs are actually running on a regular schedule.**

Every execution record is kept in a database.

Executions in the last 30 days: **81,335**

Breakdown: 80,755 succeeded / 145 failed / 435 reclaimed while still marked as running (stale)

Success rate: **99.29%**

Narrowing to the last 7 days: 20,107 runs with **6 failures** (99.97%)

Yesterday alone: **2,534 runs**

2,534 runs in a single day means that **on average, something runs automatically once every 34 seconds.** Across the entire period for which records exist, the cumulative total was over 250,000 runs.

The content ranges from posting and analyzing social media, promoting articles, post-processing YouTube videos, maintaining knowledge in Obsidian, backups, health checks, deadline reminders, and even generating this very series of articles. This article itself was born from **a job that fires every 7 days.** It automatically picks one topic from a ledger, actually has the AI read the source files backing it, and generates a draft — all the way through.

The results of every process, and the knowledge extracted from them, all get written back into Obsidian. There are **6,060 Markdown notes** , and in just the last 30 days there were **1,182 commits** (roughly 39 a day).

Knowledge is split into three types. There are **234 wiki entries** answering "what is X," **75 KB entries** answering "here's what to do when you hit this problem," and **12 ADR entries** answering "why I chose this." The daily notes, my day-to-day log, cover **479 days.**

This three-way split isn't a human filing hobby — it's for the AI's sake. When you have the AI recall "what did I do last time," having it search through one box with everything mixed together degrades accuracy. **Splitting the boxes by the shape of the question lets the AI go straight to the right box and only that box.**

Now for the main event. Writing only about what went well isn't useful, so here are the four things that actually broke.

This was the most dangerous one.

Closing an entry point means **not going to check.** In other words, you simultaneously close off the opportunity to notice that something has stopped working. If a process fails loudly with an error, a notification fires — but in reality, most failures are silent.

The measurements bear this out. Those 435 stale entries from the last 30 days are a case in point. Digging into them, **almost all 435 had been batch-marked as terminated at the exact same timestamp on the same day (July 19, 06:49:12).** In other words, they didn't fail one at a time — this is the trace of a later cleanup job sweeping up things that had been left stuck in a "running" state. No exit code was recorded. Whether a process died or the machine rebooted, nobody was watching at the moment it happened.

Since none of this was flagged as an error, if I hadn't put a cleanup job in place, these 435 records would have been stuck showing "running" forever. **The anomaly never sounded an alarm as an anomaly.**

I've had incidents of the same structure happen over and over. A process skips its work and exits normally (exit code 0, so it looks successful). A script written with relative paths misfires (zero targets found, so it looks successful). A limit-value config key is missing, so it runs wide open on the default (it's running, so it looks successful). **None of these gets reported as a "failure."**

The countermeasure was to place **actively-alerting mechanisms** on the exit side, in place of the entry point I'd closed.

Run a health-check job continuously, monitoring whether services are alive at all (it ran 8,697 times in the last 30 days)

Have a separate job that detects consecutive failures and notifies, plus a separate job that reports a weekly roundup

Question whether the notification path itself is dead. In fact, there was a period when the destination webhook had been deleted, and failure notifications kept getting silently dropped with a 404. **A state where no notifications arrive is indistinguishable from "normal."**

When in doubt, err on the side of alerting too much. The one thing you never choose is silence

If you're going to design for fewer entry points, **you must add active notifications matching the number you removed.** That's the bare minimum condition.

But once you start adding notifications, the opposite problem shows up.

People inevitably grow numb to a notification that fires every morning. Push an important deadline that only comes once or twice a year into a channel you've gone numb to, and you will absolutely never notice it. I actually had an incident where I **failed to notice a deadline for 21 days** — the kind of deadline where missing it causes real damage. The notification had arrived. It just arrived in a place that fires every day.

The lesson here was counterintuitive: **a safety net doesn't get stronger the more you add.** Every notification channel you add reduces the weight of each existing one. The effectiveness of the whole set gets diluted.

As a countermeasure, I introduced the concept of "tiers" for deadline notifications.

Tier 0 (things where missing them costs money or forfeits a right) gets isolated into **a dedicated channel that fires only about 20 times a year.** It keeps firing until I report completion

Tier 1 (monthly recurring items) goes to the normal channel, once, on the relevant day

The goal is to preserve the sense that "it fired = something's wrong." If the Tier 0 channel fired three times a day, I'd be right back where I started. So I restricted the midday and evening re-notifications to Tier 0 only. **Designing notifications is not a job of designing volume — it's a job of designing silence.**

Making Discord the entry point led me straight into a trap specific to it.

Every single Discord message becomes its own new process. That means **the working directory resets with every message.** Even if I `cd`

'd into a directory in the previous message, by the next message it's back to the default.

The worst part is that **when a relative-path process misfires, it doesn't error out.** It goes looking for a file, doesn't find it, processes zero items, and exits normally. Nothing shows up in the logs. All you get back is a report saying "done."

The countermeasure is simple, but it demands discipline.

Always write paths as absolute paths

Have every script explicitly set its working directory at the top

For long-running processes or heavy output, don't rely on stdout — **write to an absolute-path log file and read it back**

And rather than just writing this down as a rule, I placed it at the very top of the config file the AI reads. It's designed to be prevented on the AI's input side, not relying on human attentiveness.

This is the one that chilled me the most.

A phenomenon occurred where the AI followed the rules when instructed interactively, but **violated them specifically when auto-launched by the scheduler.** The cause was simple: the rule was written only in the skill's documentation, and never made it into the prompt that the automated-execution path assembles.

It behaved correctly only while a human was watching, and broke when nobody was. In an environment with fewer entry points, detecting this takes longer.

And while recounting everything to write this article, **I found one more instance of the same structural gap.**

The rules in my environment explicitly state: "use the scheduler for recurring execution; don't use cron." The reason is clear-cut — a process placed in cron leaves no execution history in the database, and no notification fires even if it fails. It's exactly the kind of breeding ground for "silent failures."

But when I actually checked, **there was one job still surviving in cron.** It was the daily backup for a certain service. It had been running since before the rule was decided, and precisely because it was running, nobody had touched it. The rule got written after the fact, and it never got applied to what already existed.

This captures the limits of what a rule can do well. **A rule only takes effect on "things you're about to write."** Anything that already existed at the moment you wrote the rule keeps living outside its reach unless you explicitly go audit for it. And because it's running fine, nobody's inconvenienced — until it stops.

There are two countermeasures. One is an operating rule: **whenever I create a new convention, search the automated-execution scripts and embed it there too.** The other is structural: **separate the side that generates from the side that inspects.**

As it happens, the very article you're reading right now is a product of that countermeasure. The articles in this series are generated automatically, but after generation, a separate inspection step runs. It cross-checks the body text against a list of words that must never be published (my employer's name, client names, internal hostnames, and so on), and **if even a single one remains, it drops the article's status to "needs revision" and marks the job as failed.**

Generate article → write body to a fixed path

↓

Inspect (a process separate from the generator)

├─ Any forbidden word remains → drop to "needs revision," fail

├─ Body was not saved → drop to "needs revision," fail

└─ Passes → notify with draft URL

The key point is that the inspection isn't left to the AI's prompt. **I don't rely on "I wrote it in the prompt, so it should be followed."** AI follows instructions most of the time, but there are kinds of mistakes where "most of the time" isn't good enough. Anything that would be irreversible on a life-altering scale gets turned into a mechanical constraint.

In the same spirit, I've kept **only the publish button in human hands.** Everything up to the draft is fully automated; publishing is human. I have no plans to automate this going forward.

It was enough. With a condition, though.

Running on two entry points only works **when the exit side has been made to actively alert, in place of the entry point you closed.** Counting it up, of the 114 jobs running on a regular schedule, **20 were jobs purely for monitoring and upkeep.** Health checks, failure alerts, backups, database cleanup, deadline reminders, detecting neglected projects — jobs that produce zero deliverables account for **18% of the total.**

I don't consider this waste — I consider it the legitimate cost of reducing entry points. **In exchange for the human no longer going to check, the system takes on the obligation to report on its own.** As long as that trade is fair, this design holds together.

Conversely, I've also become clear on how to recognize the moment when I can no longer hold the line at "two." **If I start opening some new tool's UI every day, that's a sign I'm losing.** If not opening it makes me anxious, that means my notification design is insufficient. It's not that I added one more tool — it's that I added one more entry point. When that happens, I stop going to check the UI and instead write the wiring to funnel the necessary information into Discord.

Having run this design in practice, I've narrowed down the principles that remain to five.

**1. Decide where you yourself will touch things before deciding what to have AI do.** The former expands without limit; the latter is finite. Fix the finite one first, and the rest gets automatically pushed onto the AI side.

**2. Don't demand "organizing" from an entry point.** Make it a place that only receives. The moment you make categorization, prioritization, or project assignment happen at the entry point, that entry point gets neglected.

**3. Add actively-alerting mechanisms matching the number of entry points you closed.** A design where you no longer go check only works when it's paired with a design where the system reports to you. Do only one half, and it breaks quietly.

**4. Notifications dilute as you add more. Physically split routes by importance.** The sense of "it fired = something's wrong" can only be built through frequency of firing. Deliberately reserve one channel that fires only around 20 times a year.

**5. For anything you absolutely need followed, guarantee it through inspection, not through the prompt.** Separate the side that generates from the side that inspects, and stop the process if something trips the check. AI follows instructions most of the time, but for the things where "most of the time" isn't acceptable, put up a mechanical wall.

And what actually made the biggest difference turned out to be simply counting things. In writing this article, I measured everything for real, for the first time. I didn't know, until I counted, that there were 114 jobs alive on a regular schedule, that they'd run 81,335 times in the last 30 days, or that 100% of sessions were now coming through Discord. **As for the one job left surviving in cron — if I hadn't counted, I would never have noticed it, for the rest of my life.**

**The most dangerous state is believing "it's running fine" without ever knowing the scale of your own system.** What to automate next is better decided from actual counted results, not from a feeling.

Starting next time, I'll break down, one by one, the individual systems I've built on top of this foundation — beginning with the story of how I dropped cron in favor of a queue-based approach.
