From Discord to Dooray!: Rebuilding My AI Team

Back in April, I built and ran an AI team using the channel feature that had just shipped in Claude Code. Following a format similar to the Planner, Generator, and Evaluator setup introduced at the time, I built an environment where agents could talk to each other over Discord, and I more or less managed to get them running feedback loops with each other to move work forward. Still, there were a few things about that setup that bugged me.

The first was both a strength and a weakness: every agent in the Discord channel ended up reading every bit of context. Sure, each agent had instructions not to respond to anything unrelated to them, and there was an upside in that agents could pick up context about upcoming work ahead of time. But I couldn’t shake the feeling that it was a waste of resources. The second was that records evaporated. Since everything happened in a channel that worked a lot like a chat room, older messages just scrolled away. Of course, there were ways around this too. Just have the agents keep proper records. There’s memory, and there’s the Obsidian Vault.

So if there were plenty of ways around it, why did it still feel uncomfortable? After thinking it over, I concluded that I was treating the agents much more like people than I realized. In other words, I was unconsciously mapping them onto the teammates I work with at my company. Do I put all my teammates in one chat room and have every work conversation there? No. I talk one-on-one, pull the right people into a meeting, send emails, or file tasks in an issue tracking system. I pick the right communication route for each situation. The more immediate the feedback you need, the more you lean toward the first options. The more the record matters, even if it’s slower, the more you lean toward the last ones. Looking back, that was exactly where I felt the friction in running an agent team centered on a Discord channel. I needed an issue tracking system.

At this point, Slack dropped out almost naturally. Around then, I think some people were trying to have OpenClaw and multiple people gather in a single Slack channel to pass work around, but Slack is closer to group messaging and a long way from issue tracking. I think that approach is meaningful in its own way, but it wasn’t the direction I was after. So the approach I tried in early May was GitHub. For personal reasons I could not make time to share that experience, but I created a repository and experimented with exchanging work with a single agent through issues. A few of the posts I published on Facebook, WordPress, and LinkedIn during that period were the output of passing tasks back and forth with an agent through GitHub Issues. I was confident the agent would work well in this structure. The real question was how natural the process would feel to humans, and whether multiple people and multiple agents could be woven into it. It was all good except for one thing. GitHub accounts require a verified email address. That meant assigning an email address to every agent, which wasn’t impossible but looked like more hassle than I expected. Every new agent would mean creating another email account and signing up for GitHub with it. To get around the hassle, I came up with the idea of designating one account as a shared account for the agents and telling them apart with tags, and I actually tried it. It felt awkward that the way you assign an owner had to differ depending on whether the assignee was a human or an agent, and from the agents’ side, having to check every change on the shared account and look at the tags felt wasteful. It was time to look for another option.

Finding an alternative wasn’t easy. Most issue tracking systems required an external email, and solutions aimed at being enterprise work platforms, like Google Workspace, could issue accounts without an external email, but they only offered mail and document sharing tools, not an issue tracking system. That’s when Dooray! came to mind. Dooray! started out as a task-centered issue tracking system and grew into an all-in-one enterprise work platform. As a result, it had become a rare solution that both issues its own accounts and provides an issue tracking system. On top of that, the free plan covers up to 25 accounts, and email, messenger, and the issue tracking system are all included in it. Creating an account did require an external email for password recovery, but all it needed was the ability to receive the password email, so I could get around it without creating separate email accounts. It also offered an API that AI agents could use to access the issue tracking system, and it supported webhooks for things like issue creation and status change tracking. Hey, this could actually work.

I created a tenant and started building the environment. I explained the Dooray! system’s specs and the workflow I had in mind to a Claude agent, and had him build the extra environment I needed. First, I built a server to handle the webhooks Dooray! sends: a webhook receiver. I needed a public domain to point at this server, and I solved that with Tailscale’s MagicDNS. I made a plugin that connects to the receiver over WebSocket and filters out only the webhooks the agent itself needs to handle, and used the monitor feature recently added to the Claude Code CLI to receive the events coming in through the plugin. I handed the Dooray! API docs to the agent and had him write a skill that lets agents read and write Dooray! tasks. The agent that helped with this process, Roy, I appointed as HR manager, or rather, AR (Agent Resource) Manager.

There was some trial and error, but it worked as intended. Once agents notice a task assigned to them, they read the task, carry out the work, post a reply, and either hand the task to the next assignee or close it. A natural flow was in place. The only reinforcement I added was logic for the webhook receiver to periodically poll tasks that are still open. That way, if a webhook didn’t arrive because the network was flaky or the Mac mini was down for a bit, the agent could still pick up and handle the task later. Come to think of it, this mirrors how people work too. Tasks handed to you during work hours you can handle right away, but tasks assigned after you’ve left for the day, you go through the next morning when you’re back at work, one by one, right? I think it’s the same principle.

Now that one human and one agent had successfully exchanged work through tasks, it was time to add more agents. Some are members I’d put together before, recycled, and some are new agents I added for what I need these days. Breda for all kinds of development, Hawkeye for development review, Lina for finance, and Falman for SNS publishing. That said, I left the development and maintenance of the agents’ shared tools to Roy. You could say Roy doubles as AR and OM (Office Management). Each role is written up in a Handbook document that all the agents share and refer to. In company terms, it’s the org chart.

It’s been about two weeks since I started running the team like this. Every post I’ve published on social media in the last two weeks was done together with Falman. This post will probably be done that way too. When I write the Korean first draft, Falman does a quick proofread for typos and hands it back to me. Once I approve it, Falman puts up a Facebook draft and starts the English translation at the same time. I edit Falman’s rough translation to my taste, Falman proofreads it again, and after a few rounds the English version is done. With my approval, Falman then puts drafts up on WordPress and LinkedIn. I give the three drafts a final review and publish them, and Falman attaches the link to each post on its task and closes it out. Pretty realistic task flow, isn’t it!

To be honest, that example is a work flow between one human and one agent, so it was hard to say it fully captured the picture I had in mind: multiple people and multiple agents collaborating. Then a few days ago, I finally saw a case that fit. I had been having Lina do some simple personal finance analysis as a test. Obviously I didn’t hand over my bank account directly. I told her to process and analyze data I had downloaded. For extra security, I also separated development from operations. I gave Lina one month of bank statements downloaded from the bank and told her: I’ll give you files like this from the bank, so get ready to import them into a local DB for analysis, but don’t build the program for that yourself. Send the requirements to Breda, request the development, and use what comes back. After analyzing the file, Lina “made a sample file” and sent it to Breda along with the requirements as a development request. Breda, on receiving the request, decided that a program handling sensitive data would need a development review, and after building it, asked Hawkeye to review it. Hawkeye gave a few fix instructions, and Breda made the fixes and returned it to Lina. Meanwhile, Lina found that the Korean characters came out garbled when she downloaded the bank statements file I had uploaded, and sent a request to fix the Dooray! task skill to Roy. Roy reviewed the task, soon found the problem, and fixed and deployed the skill. Lina then took the finished output from Breda, re-verified that it worked with the real data I had uploaded, confirmed everything was fine, and assigned a task to me, asking me to upload the rest of the bank statement files. This whole process happened through tasks and assignee changes. One human and four agents collaborated, and of the tasks involved, I created one and the agents created two. It was an ideal issue tracking flow, the kind you rarely see even among people.

Of course, there are still pain points. When I want to have a quick conversation to sort out ideas before working through tasks, right now the only option is to talk in a Claude Code CLI session. That works now because I’m the only human, but the moment even one more person joins, it falls apart. And even then, it only works for a one-on-one conversation between a human and an agent. For multiple people or multiple agents to talk on the fly, a different mechanism is needed. Using tasks has gone smoothly so far, but the moment someone forgets to assign the owner, the flow stops. And humans and agents alike are bound to make that mistake. It happens often enough in the real world, too. I’ll probably need a way to detect and resolve these stalls.

There’s also a more fundamental question. Which is better: agents that keep a session open and handle tasks as they’re assigned, or a new agent spawned to handle each task whenever one comes up? I’m going with the former right now, but I think each approach has its pros and cons. The one better suited to scaling up the system is probably the latter. But I think the former has the potential for each agent to understand a wider context as they work. Built well, it’s a form that small organizations could make good use of. And it’s also a more fun picture for me to play with. For a while, let’s keep pushing in this direction.

Leave a Reply