<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Juha Pellotsalo</title>
    <description>The latest articles on DEV Community by Juha Pellotsalo (@juhapellotsalo).</description>
    <link>https://dev.to/juhapellotsalo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3672359%2F57004405-3cc2-4cc6-abe6-f7e8bd9a21fa.png</url>
      <title>DEV Community: Juha Pellotsalo</title>
      <link>https://dev.to/juhapellotsalo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/juhapellotsalo"/>
    <language>en</language>
    <item>
      <title>Building a Personal Agent</title>
      <dc:creator>Juha Pellotsalo</dc:creator>
      <pubDate>Tue, 28 Apr 2026 13:09:44 +0000</pubDate>
      <link>https://dev.to/juhapellotsalo/building-a-personal-agent-502l</link>
      <guid>https://dev.to/juhapellotsalo/building-a-personal-agent-502l</guid>
      <description>&lt;p&gt;Shortly after OpenClaw came out I started building my own personal agent. I picked Claude Code as the harness, partly out of habit and partly because I wanted to see what it could do outside of coding.&lt;/p&gt;

&lt;p&gt;The agent lives in a single directory on my file system. Launching Claude in that folder launches the agent. Nothing about it is Claude-specific, though. It runs on skills, MCPs, and custom CLI commands, and stores everything in markdown or YAML. Any harness can work with these concepts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bootstrapping
&lt;/h2&gt;

&lt;p&gt;Each session starts by loading &lt;code&gt;AGENT.md&lt;/code&gt; (or &lt;code&gt;CLAUDE.md&lt;/code&gt; in this case). It's deliberately compact, just enough to point the agent in the right direction:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Agent identity and a link to &lt;code&gt;SOUL.md&lt;/code&gt;, which holds the full description.&lt;/li&gt;
&lt;li&gt;Operating principles, like "auto-improve custom CLI commands when they fail."&lt;/li&gt;
&lt;li&gt;A short note on how skills are organized and how memory works.&lt;/li&gt;
&lt;li&gt;Rules for formatting bash commands so they pass permission lists cleanly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything else loads on demand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Skills, CLIs, and the file system
&lt;/h2&gt;

&lt;p&gt;Three pieces do most of the work, so it's worth introducing them up front.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skills&lt;/strong&gt; are the agent's playbook. Almost every action it takes is driven by one. A skill contains instructions for calling CLIs, with examples and guardrails, and procedures for things like compiling memory prints, priming sessions, and writing or reviewing code. I use relatively few skills with larger instruction sets, rather than a long catalog of small ones. Sessions typically begin with a skill call appropriate to the task. If I'm working on a project, &lt;code&gt;/project&lt;/code&gt; primes the session by reading the project wiki.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CLIs&lt;/strong&gt; are the arms and hands. They're custom-built commands the agent executes via bash, mostly thin wrappers around APIs: &lt;code&gt;calendar-cli&lt;/code&gt;, &lt;code&gt;gmail-cli&lt;/code&gt;, &lt;code&gt;drive-cli&lt;/code&gt;. &lt;code&gt;reddit-cli&lt;/code&gt; reads posts as JSON. &lt;code&gt;youtube-cli&lt;/code&gt; pulls video transcripts. Going through CLIs instead of MCP gives me clearer control. The Google CLIs, for example, support multiple accounts, and the right credentials get picked up in code rather than from an agent-generated bash script.&lt;/p&gt;

&lt;p&gt;CLI calls are also cheaper than MCP calls, and I can bake error correction into the code itself. LLMs love to hallucinate imaginary args, and validating those inside the CLI is trivial. The validation error returns the correct usage, so the agent fixes the call on the next try instead of looping through trial and error.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The file system is the database.&lt;/strong&gt; Markdown and YAML for everything. Folder structure is the schema.&lt;/p&gt;

&lt;h2&gt;
  
  
  Markdown as a data store
&lt;/h2&gt;

&lt;p&gt;Journals and logs are the unstructured side of this. The structured side looks more like a row in a database: front matter defines the shape, the body holds the content.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;project-axiom&lt;/span&gt;
&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;active&lt;/span&gt;
&lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;high&lt;/span&gt;
&lt;span class="na"&gt;related&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;agent-system&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;langgraph-experiments&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# The Axiom&lt;/span&gt;

Notes and references for the agentic newsroom project...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These files reference each other like foreign keys, with links as plain paths. This works because LLMs are, for some reason, very good at reasoning over directory trees, and markdown is plain text the model reads natively. Binary database files are opaque by comparison.&lt;/p&gt;

&lt;p&gt;The catch is hallucination. Despite clear instructions, the agent will occasionally write a markdown that doesn't match the defined shape, which immediately breaks anything that reads it.&lt;/p&gt;

&lt;p&gt;To handle that, I use a third-party tool called &lt;a href="https://github.com/nfrith/als" rel="noopener noreferrer"&gt;ALS&lt;/a&gt;. A hook fires whenever a data markdown is edited, ALS validates it against the shape, and on any error it returns a correction message to the agent. It's pure code, deterministic, free, and faster than any agentic validation loop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memory
&lt;/h2&gt;

&lt;p&gt;The first thing I implemented was memory. Initially it was just a text dump into &lt;code&gt;MEMORY.md&lt;/code&gt;, but I wanted memories from day one so I'd have a record of building the agent itself. Almost everything else can be re-created. Those chronological footprints can't.&lt;/p&gt;

&lt;p&gt;The current system is a journal spread across markdown files, one per day:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;memory/
└── journal/
    ├── 2026-03/
    └── 2026-04/
        ├── 01.md
        ├── 02.md
        └── ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;code&gt;/remember&lt;/code&gt; skill collects memories at the end of each session. Daily files are split into topics, and if I work on the same topic across sessions, the skill bakes new memories into the existing topic by rewriting the whole file. It's a heavy operation, both in tokens and time, which is why one day is the smallest unit. It's small enough not to choke the agent during a rewrite. The next step is probably per-topic daily files.&lt;/p&gt;

&lt;p&gt;Memories are also indexed into a file-based SQLite-vec store in the same folder. A hook fires on every journal edit and re-chunks the file. Chunk size is dynamic, anchored on section headers, so each topic becomes one chunk, tagged with the header and filename as metadata.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;/recall&lt;/code&gt; skill handles retrieval. The topic structure already creates clean semantic boundaries, which makes search effective on its own. On top of that, the final retrieval is hybrid: vector similarity blended with BM25 keyword scores at 70/30.&lt;/p&gt;

&lt;h2&gt;
  
  
  Knowledge bases
&lt;/h2&gt;

&lt;p&gt;This part borrows from Andrej Karpathy's idea of LLM knowledge bases. There's a &lt;code&gt;raw/&lt;/code&gt; folder in the project root where the agent dumps anything mid-session: notes, screenshots, snapshots. Each night a scheduled task compiles those into a wiki, blending new material into what's already there. The wiki is a continuously updated snapshot of what I've been thinking and working on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Projects
&lt;/h2&gt;

&lt;p&gt;Almost every session is tied to some project: code, research, or work on the agent itself. A project is the basic unit of work. &lt;code&gt;PROJECT.md&lt;/code&gt; holds the instructions, and each project has its own knowledge base that compiles into a self-updating wiki.&lt;/p&gt;

&lt;p&gt;The agent also has project management built in. A Trello-like board with lists and cards, all stored as markdown.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;card-042&lt;/span&gt;
&lt;span class="na"&gt;list&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;in-progress&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Implement /recall hybrid retrieval&lt;/span&gt;
&lt;span class="na"&gt;created&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2026-04-12&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

Blend vector similarity with BM25 at 70/30. Validate on
last week's journal entries...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a project session primes, the board loads into context so the agent always has the full scope of what's planned. The board is also modeled as a data store shape, which lets a small custom backend read it directly. More on that next.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core and heartbeat
&lt;/h2&gt;

&lt;p&gt;The agent system has a custom daemon running in the background. It's a cron-like scheduler that fires fresh agent sessions in headless terminals on a schedule. Each session has a small custom system prompt, but otherwise it's the same agent I use interactively, just running on its own.&lt;/p&gt;

&lt;p&gt;A heartbeat task runs every 30 minutes. It backs up the system and pushes it to a remote git repo. Nothing more dramatic than that, but it means the agent's accumulated state is never more than half an hour from being safe.&lt;/p&gt;

&lt;h2&gt;
  
  
  Web apps on top
&lt;/h2&gt;

&lt;p&gt;Most of my interaction is through the Claude CLI, typing and talking. But some things are easier to see than to describe.&lt;/p&gt;

&lt;p&gt;The kanban board is the clearest example. A small Trello-like web app reads the same raw markdown files the agent does, which is safe because ALS guarantees the format and referential integrity hold. The web layer doesn't own the data. It just renders it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this goes
&lt;/h2&gt;

&lt;p&gt;A personal agent is a useful tool on its own, but it becomes something different once it has history. Memories, knowledge bases, project notes, access to my email and accounts and Spotify feeds. Every interaction is stored, and the agent's picture of me sharpens with each session.&lt;/p&gt;

&lt;p&gt;It's not finished though. Claude Code is a worker harness. It's exceptional at coding and code-adjacent tasks, and bad at being a person. There's no real personality, no conversational nuance, and any character I write into &lt;code&gt;SOUL.md&lt;/code&gt; gets diluted past the first few turns by the harness's own system prompt.&lt;/p&gt;

&lt;p&gt;The natural next step is splitting the agent in two: a conversational layer on top, a worker layer underneath. The conversational layer would run on a different harness, with LangChain Deep Agents as my current candidate, and exist purely as the interface I talk to, delegating real work downward. That separation is what would let a personality actually take hold and evolve through memory, instead of getting flattened on every prompt.&lt;/p&gt;

&lt;p&gt;The other missing piece is autonomy. Right now the agent is almost entirely interactive. Claude Code's recent auto-mode is a step in the right direction. It skips manual permission prompts in favor of a dedicated permission model. It's not quite there yet, but for an agent to run long tasks unattended, something like it is essential.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>claude</category>
      <category>personalagent</category>
    </item>
    <item>
      <title>Building a Smart Storage Facility Prototype with BMAD</title>
      <dc:creator>Juha Pellotsalo</dc:creator>
      <pubDate>Mon, 02 Feb 2026 03:54:58 +0000</pubDate>
      <link>https://dev.to/juhapellotsalo/building-a-smart-storage-facility-prototype-with-bmad-5155</link>
      <guid>https://dev.to/juhapellotsalo/building-a-smart-storage-facility-prototype-with-bmad-5155</guid>
      <description>&lt;p&gt;I wanted to build something that takes the usual chat-with-data bot further. I created a fictional storage facility equipped with several environmental sensors: motion detectors, temperature monitors, and air quality sensors. These are laid out on a blueprint view split into several zones: loading bay and different types of storage rooms. This approximates where sensors would be in a real-life layout.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beyond the typical chat panel
&lt;/h2&gt;

&lt;p&gt;The UI integrates with an assistant panel that resembles the typical assistant chat view. But the UI explores options to click sensors and other elements of the system that auto-generate messages and send them to the assistant. Instead of typing everything (which the user can always do), they have easier UI elements to drive the conversation.&lt;/p&gt;

&lt;p&gt;The system automatically scans the data and detects anomalies such as a rising cold room temperature. It flags warning scenarios in the UI and pre-formats them with button-clickable elements to query more info from the assistant. The system can generate formal incident reports, run compliance audit checks, and similar actions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dynamic visualization generator
&lt;/h2&gt;

&lt;p&gt;There's also a dynamic visualization generator that works the same way as Claude artifacts. It first generates a handful of visualization ideas based on the system status and then proceeds to generate a React component rendering the visualization, which gets dynamically executed in a designated UI component.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I build these prototypes
&lt;/h2&gt;

&lt;p&gt;I've found building these quick prototypes extremely useful because it improves my ability to rapidly prototype using Claude Code. I also try to experiment with something new each time to learn more and to boost efficiency.&lt;/p&gt;

&lt;p&gt;With this project I experimented with the &lt;a href="https://github.com/bmad-code-org/BMAD-METHOD" rel="noopener noreferrer"&gt;BMAD method&lt;/a&gt;. It's a system that tries to emulate established methodologies like scrum in an agentic way. At its core, BMAD is a collection of 68 workflows and processes modeled as prompts, executed by 26 specialized agent personas. The whole system follows a four-phase cycle: Analysis, Planning, Solutioning, and Implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  How BMAD works
&lt;/h2&gt;

&lt;p&gt;The full default flow starts with analysis and brainstorming to collect product requirements. It splits these into epics and further down to stories that are then implemented one at a time. There are separate flows to design UX, run tests, and so on. Each of these is executed with a specific agent role activated.&lt;/p&gt;

&lt;p&gt;The core idea is that these predefined agent personas, when activated, always do the tasks the same way across the entire project. This is important because when you're just freely prompting, the conversation with Claude tends to steer a certain way, and these subtle shifts affect how and what Claude writes, leading to inconsistent artifacts. BMAD calls this "solutioning," the third phase of their cycle, focused on keeping the process consistent.&lt;/p&gt;

&lt;h2&gt;
  
  
  My experience with BMAD
&lt;/h2&gt;

&lt;p&gt;I've never felt comfortable following any process strictly down to the last detail. They tend to be too rigid, work sometimes in some areas but restrict in others. BMAD is no exception because it doesn't quite fit my personal style. Brainstorming and ideation was extremely useful, but the implementation flow with repeated steps of creating a story and developing it felt a little tedious.&lt;/p&gt;

&lt;p&gt;That said, I can absolutely see great value in following this process: it produces written artifacts that persist where you are in the development process. This is a pattern commonly used in &lt;a href="https://github.com/langchain-ai/deepagents" rel="noopener noreferrer"&gt;deep research agents&lt;/a&gt; where parts of the process are constantly stored on the file system. This helps immensely with Claude Code's main challenge: context window management. Running extensive one-shot tasks consumes the context window very quickly, leading to compacting which never really works well. It's far more optimal to clear the context frequently and then quickly continue where you left off. BMAD's doc artifacts help with exactly that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adversarial code review
&lt;/h2&gt;

&lt;p&gt;Another useful feature is BMAD's adversarial code review. First-shot Claude code rarely produces the most optimal result and doesn't always account for architectural structure. The adversarial review process systematically looks for problems in the code, running multiple passes to identify vulnerabilities and propose improvements. It includes explicit guidance on handling false positives. This fits well with my style of iterating between quick one-shot implementation and structural revisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;BMAD isn't perfect, but I think it's a step in the right direction. It's the first serious attempt I've come across to use AI to drive its own development process. This kind of engineering structure is necessary. Otherwise you need to constantly run the same prompts to clean up the code and architecture and instruct the harness to pick up where you left off before the context window filled up.&lt;/p&gt;

&lt;p&gt;Claude Code has made it extremely easy to take high-quality open source projects, reverse engineer them, and tailor them to your own needs. That's exactly what I started doing: take what works in BMAD, then create my own version that uses the same patterns but tailored in a way that fits my development process.&lt;/p&gt;

&lt;p&gt;The full project code is available in this &lt;a href="https://github.com/juhapellotsalo/facility-intelligence-system" rel="noopener noreferrer"&gt;repo&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>langgraph</category>
      <category>claude</category>
      <category>prototyping</category>
    </item>
    <item>
      <title>Agentic Content Scout: Exploring LangGraph’s Handoff Pattern</title>
      <dc:creator>Juha Pellotsalo</dc:creator>
      <pubDate>Mon, 19 Jan 2026 03:40:56 +0000</pubDate>
      <link>https://dev.to/juhapellotsalo/agentic-content-scout-exploring-langgraphs-handoff-pattern-82a</link>
      <guid>https://dev.to/juhapellotsalo/agentic-content-scout-exploring-langgraphs-handoff-pattern-82a</guid>
      <description>&lt;p&gt;With this project, I wanted to experiment with the &lt;code&gt;create_agent&lt;/code&gt; pattern in LangGraph. This was previously known as &lt;code&gt;create_react_agent&lt;/code&gt;, but it was renamed in the 1.0 release. I actually think the original name was more descriptive because it explicitly implements the &lt;strong&gt;ReAct&lt;/strong&gt; (Reasoning and Acting) pattern. &lt;/p&gt;

&lt;p&gt;ReAct is a fundamental building block for agentic applications. It is a simple but powerful loop: the agent receives instructions, uses its tools to reason and execute, and then reflects on the results until the task is complete.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Supervisor and Orchestration
&lt;/h2&gt;

&lt;p&gt;Another goal was to explore the supervisor (or orchestrator) pattern via a conversational CLI. The setup is similar to tools like Claude Code where the user interacts through a command line. &lt;/p&gt;

&lt;p&gt;In this architecture, user queries go to a &lt;strong&gt;Supervisor&lt;/strong&gt; agent first. Its primary job is to determine intent. Once it understands what the user wants to do, it delegates the work to a specific subagent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Handoffs Matter
&lt;/h2&gt;

&lt;p&gt;The delegation happens using the &lt;strong&gt;handoff pattern&lt;/strong&gt;, which is different from standard execution flows. In many systems, a supervisor acts as a middleman for every single interaction. This becomes a bottleneck in conversational systems that require &lt;strong&gt;Human-in-the-Loop (HITL)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If a subagent needs to ask the user for clarification, a traditional flow would require the subagent to pass control back to the supervisor, which then asks the user, receives the answer, and passes it back again. &lt;/p&gt;

&lt;p&gt;I think of this as &lt;strong&gt;micromanagement vs. full delegation&lt;/strong&gt;. In real life, you want to hand off a task and say, "Go do this and let me know when it's done." You don't want to be bogged down by the day-to-day details of how the subagent executes. The handoff pattern allows the subagent to own the conversation with the user directly until its specific task is finished.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the Content Scout
&lt;/h2&gt;

&lt;p&gt;The Agentic Content Scout allows users to track specific topics, like "AI development news" or "Open world video games." You can define preferences for each topic—for example, prioritizing academic research over marketing fluff, or avoiding social media in favor of reputable news outlets.&lt;/p&gt;

&lt;p&gt;The system uses two subagents:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Topic Manager&lt;/strong&gt;: Handles the CRUD operations for maintaining topics and preferences.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content Scout&lt;/strong&gt;: Uses the Tavily search tool to find and retrieve articles.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How the Graph Works
&lt;/h2&gt;

&lt;p&gt;The system is built as a LangGraph main graph using &lt;code&gt;MemorySaver&lt;/code&gt; as a checkpointer to maintain state. The execution loop follows these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Input&lt;/strong&gt;: The user sends a command like "create a topic for AI safety." &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Intent&lt;/strong&gt;: The Supervisor receives the message and decides to call the &lt;code&gt;handoff_to_topics&lt;/code&gt; tool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Command&lt;/strong&gt;: The handoff tool returns a LangGraph &lt;code&gt;Command&lt;/code&gt; object. This tells the graph to stay within the agent node but switch the &lt;code&gt;active_agent&lt;/code&gt; state to &lt;code&gt;topic_manager&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ownership&lt;/strong&gt;: The Topic Manager takes over the conversation. If it needs more info, it calls a &lt;code&gt;gather_preferences&lt;/code&gt; tool which triggers a LangGraph &lt;code&gt;interrupt()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pause and Resume&lt;/strong&gt;: The graph saves its state and returns control to the CLI. Once the user answers, the checkpointer restores the state and the Topic Manager resumes exactly where it left off—without the supervisor ever being involved.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Completion&lt;/strong&gt;: Once the subagent finishes, it hands back a summary to the Supervisor, which provides the final response to the user.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The beauty of this pattern is that the supervisor truly delegates. It doesn't micromanage or relay messages. The subagent handles everything, including user interactions, and only reports back when done. The graph's single node design with dynamic routing makes handoffs clean: you just update a state field and loop.&lt;/p&gt;

&lt;p&gt;Here is the repo: &lt;a href="https://github.com/juhapellotsalo/agentic-content-scout" rel="noopener noreferrer"&gt;https://github.com/juhapellotsalo/agentic-content-scout&lt;/a&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>architecture</category>
      <category>llm</category>
    </item>
    <item>
      <title>Why Claude Code Excels at Legacy System Modernization</title>
      <dc:creator>Juha Pellotsalo</dc:creator>
      <pubDate>Sun, 11 Jan 2026 03:56:18 +0000</pubDate>
      <link>https://dev.to/juhapellotsalo/why-claude-code-excels-at-legacy-system-modernization-1ll1</link>
      <guid>https://dev.to/juhapellotsalo/why-claude-code-excels-at-legacy-system-modernization-1ll1</guid>
      <description>&lt;p&gt;Nobody sets out to build a legacy system. They begin as well-designed solutions to real problems. They work so well they become critical infrastructure. Then time passes, requirements accumulate, developers rotate, and one hasty fix at a time the system becomes something nobody fully understands anymore.&lt;/p&gt;

&lt;p&gt;We (senior developers) all know the story. The outdated library that's too risky to upgrade, the undocumented script discovered on a production server. Bugs that only manifest on Tuesdays for accounts created after February. When it finally becomes clear the system needs to be rewritten, estimates come in: six figures, multi-year timelines, full teams deployed.&lt;/p&gt;

&lt;p&gt;I spent the last months exploring agentic AI applications but so far the most practical value I've found is simpler: Claude Code is exceptionally good at exactly those tasks that make legacy modernization so painful for humans.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dependency archaeology
&lt;/h2&gt;

&lt;p&gt;Legacy systems accumulate libraries that are outdated, discontinued, or simply vanished from the internet. Claude Code can scan the codebase, identify the worst offenders, and suggest modern replacements. Trivial dependencies can be written from scratch, eliminating the external dependency entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reverse engineering at scale
&lt;/h2&gt;

&lt;p&gt;A decade-old system often contains hundreds of thousands of lines written by dozens of developers, most of whom left no documentation. It takes months for a human engineer to understand this code well enough to safely modify it. Claude Code generates readable summaries and traces logic flows tirelessly, producing in hours what would take weeks of careful reading.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dead code identification
&lt;/h2&gt;

&lt;p&gt;Legacy codebases bloat because deletion is risky. New features get added but old code rarely gets removed. Cross-referenced with production logs, Claude Code identifies what's actually executing versus what's just taking up space.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exposing fossilized hacks
&lt;/h2&gt;

&lt;p&gt;Quick fixes have a way of becoming permanent fixtures. It's not unusual for a legacy app to be entangled with its original dev environment: hard-coded scripts, file-system paths set years ago that have since cemented into load-bearing parts of the application. These are notoriously difficult for humans to trace but CLI-driven agent coders excel at exactly this kind of detective work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generating a preliminary spec
&lt;/h2&gt;

&lt;p&gt;Perhaps the most valuable output is turning the existing application into a readable specification with minimal human effort. Claude Code extracts what the system actually does, how components interact, and which business rules are embedded in the logic. The result is a solid foundation for a proper spec that humans can review and refine rather than having to create from scratch. For systems where the original requirements are long lost or hopelessly outdated, this alone can save months.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This changes the economics dramatically. Detective work that previously took months of senior developer time can happen in days. The system that seemed untouchable becomes approachable. One capable developer armed with sound Claude Code skills can get the work well under way without having to deploy a full team. &lt;/p&gt;

&lt;p&gt;This isn’t speculative. Last week I analyzed an Android app repository I had not seen before and fixed an old issue. The pull request was approved the same afternoon. This would’ve been impossible a year ago, which goes to show how fast the tools are developing and how good they’ve already become.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claudecode</category>
      <category>legacycode</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Reflections on building my first LangGraph project</title>
      <dc:creator>Juha Pellotsalo</dc:creator>
      <pubDate>Mon, 22 Dec 2025 06:30:47 +0000</pubDate>
      <link>https://dev.to/juhapellotsalo/reflections-on-building-my-first-langgraph-project-3b6j</link>
      <guid>https://dev.to/juhapellotsalo/reflections-on-building-my-first-langgraph-project-3b6j</guid>
      <description>&lt;p&gt;I recently completed my first LangGraph project that was more than a simple tutorial. It simulates a newspaper editorial workflow where a set of agents turn a story idea into a finished article. The newsroom itself wasn’t the goal, I simply used it to learn LangGraph properly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learning LangGraph
&lt;/h2&gt;

&lt;p&gt;I explored several frameworks, including OpenAI Agents SDK, CrewAI, and AutoGen, but eventually settled on LangGraph. Modeling the application as a graph felt natural, and the level of control appealed to my background as a senior engineer.&lt;/p&gt;

&lt;p&gt;I started with Udemy courses and Medium posts, but the best material came from LangChain’s own &lt;a href="https://academy.langchain.com/" rel="noopener noreferrer"&gt;academy&lt;/a&gt;. The LangGraph foundations and deep research project courses were the two most useful ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modeling agents as subgraphs
&lt;/h2&gt;

&lt;p&gt;The system ended up being a mostly linear workflow with agents such as Assignment Editor, Research Assistant, and Reporter. I modeled each agent as its own subgraph with a single responsibility.&lt;/p&gt;

&lt;p&gt;This worked well. I could spend a couple of days improving the Reporter, then move on to the Graphics Desk. Once I was happy with the individual agents (subgraphs), stitching them together into a parent workflow graph was trivial.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prompt management was a surprising challenge
&lt;/h2&gt;

&lt;p&gt;I wasn’t expecting this, but keeping track of which prompt does what quickly became difficult. Several agents shared things like guardrails and writing guidelines, and sharing these without duplicating or contradicting instructions was surprisingly hard.&lt;/p&gt;

&lt;p&gt;In an agentic system, prompts are effectively code, but because they’re written in natural language, they lack the structure and constraints of a programming language.&lt;/p&gt;

&lt;p&gt;I ended up using XML-style elements in prompts to indicate things like &lt;code&gt;&amp;lt;Task&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;Output Format&amp;gt;&lt;/code&gt;. This probably helps the model, but it definitely helped me keep things organized. This is also what Anthropic recommends in their &lt;a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents" rel="noopener noreferrer"&gt;context engineering&lt;/a&gt; guide.&lt;/p&gt;

&lt;h2&gt;
  
  
  LangSmith for tracing
&lt;/h2&gt;

&lt;p&gt;You can enable LangSmith tracing simply by providing an API key. It’s the easiest way I’ve found to add tracing with a usable UI, and I learned very quickly that it’s a must-have. You simply cannot build an agentic system without tracing.&lt;/p&gt;

&lt;p&gt;LangSmith also includes built-in evaluation tools, which I didn’t use in this project. That’s an area that clearly needs more attention, and if I were to extend this system, LangSmith would be my starting point for proper evaluation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Editing long-form articles
&lt;/h2&gt;

&lt;p&gt;Editing the articles turned out to be one of the hardest problems. The first draft always needs several rounds of reflection and revision. It’s easy enough to analyze factual or stylistic issues, but fixing them is much harder.&lt;/p&gt;

&lt;p&gt;A full feature article can be around 2,000 words. Single-shot rewrites often fix some problems but introduce new ones, and the system easily gets stuck in a review–revise loop where each iteration drifts further from the original.&lt;/p&gt;

&lt;p&gt;I wasn’t able to solve this completely. The best results came from revising the article section by section, giving the model one section to edit along with the preceding and following sections to preserve flow. This worked much better, but increased latency and token usage beyond what made sense for a portfolio project. It is, however, the approach I’d try in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Skills as a software pattern
&lt;/h2&gt;

&lt;p&gt;I only noticed this afterward, but LangChain has a section in their documentation about &lt;a href="https://docs.langchain.com/oss/python/langchain/multi-agent/skills" rel="noopener noreferrer"&gt;skills&lt;/a&gt;. This is the same skills concept Claude Code introduced some time ago, but framed more explicitly as a software pattern.&lt;/p&gt;

&lt;p&gt;This would have been a good fit for my Research Assistant agent. It doesn’t rely on a single master prompt; instead, each node behaves like a small sub-agent. Generating web search queries is one skill, curating results is another, and packing them into state is a third. Modeling these as skills would likely make the code cleaner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;I like LangGraph. Once it clicks, modeling systems as explicit graphs and subgraphs feels natural, especially coming from a traditional software engineering background.&lt;/p&gt;

&lt;p&gt;The biggest drawback is the learning curve. If you’re building something for clients, it’s worth being aware that you can accumulate technical debt quickly. I’d probably start with a lower-code framework like n8n or CrewAI to prototype, and only switch to LangGraph if that doesn’t scale—or if there’s a team willing and able to maintain a more complex system.&lt;/p&gt;

&lt;p&gt;The full project code is available in this &lt;a href="https://github.com/juhapellotsalo/agentic-newsroom" rel="noopener noreferrer"&gt;repo&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>langchain</category>
    </item>
  </channel>
</rss>
