← Home
· 10 min

Work Recap 2026-06 to 2026-09 : Rejoining the Company

The Period

I left the company in August 2025, as told in the previous recap. After a career break, I rejoined it. This recap covers my work from June to September 2026, one piece of work per month.

2026-06 : Building a Monitoring System

Things I considered

The observability of a web application is important. If it is hard to build a local test environment for the application because of complex dependencies, observability is worth the effort. A monitoring system stores logs and metrics that help find the causes of application failures.

Context

An observability issue surfaced as a common problem across departments. The team was about to address it by adopting metric visualization and alerting. Since I had experience building a monitoring system, I volunteered and took on the task.

Design

I designed the whole architecture, including the backend system and the alarm channels, within the resource constraints given by the team leader. I specified the target metrics to be managed (SLI) and applied general thresholds to them.

Contributions

  • Built a system containing Grafana and Prometheus in a container environment using Docker Compose.
  • Provisioned and integrated Grafana alerting with SMTP and Microsoft Teams.
  • Conducted E2E tests under simulated stress conditions.
  • Staged and finalized the production deployment.
  • Controlled access through limited, authorized account registration.
  • Documented and shared the knowledge with colleagues.

Challenges

I suggested a central monitoring system on an independent node for availability, but it was not accepted because of the team's infrastructure constraints. I also suggested adopting Loki for log aggregation, but it was not accepted because the reviewers did not reach a consensus.

2026-07 : Migrating the Subject Import System from a Third Party

Context

A prototype of a subject information import system was in the development stage. It was a script written in TypeScript that transported data crawled from a third party's website to the backend every midnight. Since the system orchestrating those import jobs was not the backend, it was hard to trace why errors occurred. I took on the task of restructuring this system to make it more manageable.

Design

I analyzed the existing system and worked out an improved architecture. I decided where each feature should live according to the responsibility of each application. I kept the contract and the logical processes as they were, but refined and refactored them for robustness.

I upgraded the one-time script to a Node.js server and assigned the crawling feature to it, while moving the other logic to the backend. Crawling stayed on an external Node.js server because the web browsing library is huge and its deployment cycle is independent of the backend.

I let the backend control and orchestrate the whole workflow. It requests crawled raw data from the Node.js server, parses it into refined data, and finally commits it to the database.

Contributions

  • Simplified the Node.js server's web browsing logic by switching the library from Selenium to Playwright.
  • Improved the backend's validation of the LLM's dynamically derived mapping response to preserve data invariants.
  • Defined a dedicated thread for the work to avoid race conditions and release the Spring Scheduler's thread immediately.
  • Turned silent warnings that were easy to ignore into explicit errors.
  • Reinforced exception handling and improved traceability by adding logging.
  • Built a pipeline that pushes the Node.js server image to a remote image registry (ECR) in AWS, and configured the permissions for managing the image.
  • Focused on runtime-agnostic logic for easier testing.
  • Conducted E2E tests in a local environment and staged the work to the dev server.
  • Documented and shared the knowledge with colleagues.

Challenges

I reviewed the Spring Batch framework for this batch work, but I didn't adopt it because:

  • Many of the steps needed HTTP communication, such as web crawling. Since it takes a long time, the transaction was hard to manage.
  • Spring Batch is well suited to chunk-oriented processing, but the data in this job was too small.

2026-08 : Taking Over a New System

Context

The project is a web service that manages clinical trial documents, known as an eTMF (electronic Trial Master File).

It was planned by another department and was being developed by an outsourced team. On the first day of August, it was decided that the project would be handed over to my team.

I was the backend developer preparing to take it over. I received a snapshot of the backend and frontend source code and started analyzing it.

The problems I faced and what I did

The backend was a typical AI-generated project.

  • Unnecessary AI-generated Markdown files were there, unmanaged. They looked likely to drift as the project grew.
  • There was no test code in the source, so nothing verified how the code behaved. If I needed to edit a class, it could become a mess because of side effects.
  • Boolean values were stored as literal characters and handled as String in the project. Logic that tested whether something was true was testing whether it equaled the literal "Y". It would confuse developers like me.
  • There were some God classes. About 30 classes exceeded 1,000 lines, and about 5 were around 3,000 lines.

The outsourced development was extended to September. Refactoring all the code at that time risked conflicts when integrating the finalized code later. To avoid that risk, I listed backlog items instead of editing the source code.

Then I focused on building the cloud infrastructure that the app would be integrated with. I communicated with the infrastructure manager in my company, specified the architecture, and configured it.

I integrated the external infrastructure resources into the app with minimal code changes:

  • Migrated from configuration based on static API keys to the default credential provider chain for S3, RDS, SQS, and SES.
  • Simplified and organized the application properties into explicit environments using env postfixes.
  • Built a CI/CD pipeline with AWS CodePipeline.

2026-09 : Company AX Challenge

The challenge

My company held an Augmented Experience (AX) Challenge. It required submitting a document describing how you used AI to improve your work. I joined the challenge as a solo team.

I gave a presentation about my project at the company. It won the 2nd prize among 20 submissions.

Problem context

At that time, I was having difficulty with the manual testing of the software we were taking over.

There were about 260 specified acceptance tests. Three people (me, the frontend developer, and the PM) tested independently. It took a lot of time.

Every time the software version changed, it had to be tested again, because we couldn't be sure all the tests would still pass.

And even when we checked that a test case had passed, we couldn't be sure it had actually passed, since there was no evidence.

Objectives and approach

I set three objectives.

  • Let an agent test for me
  • Reduce the effort of repeating tests
  • Make tests leave evidence

And I adopted some tech:

  • Playwright for automating web browsing
  • The Anthropic Agent SDK for building a local agent
  • Next.js for integrating a visual app with the system

Then I started the detailed design.

I designed a self-correction loop:

  1. A test case is handed to the Tester Agent.
  2. The Tester Agent reads it and explores the target app with a web browsing tool.
  3. The Tester Agent writes a spec script for the test using Playwright and reports that the script is ready.
  4. The system runs it for the agent.
  5. If it fails, the system gives feedback to the agent and asks it to improve the script.
  6. These steps repeat until the spec script passes.

I added a supervisor loop wrapping the previous loop:

  • When the Tester Agent reports any of APP_DEFECT, CASE_MISS_MATCH, or BLOCKED, a Supervisor Agent analyzes the problem.
  • If the Supervisor Agent decides the problem is critical and other case runs are likely to fail, it returns STOP_RUN to the system and reports the problem context to the user.

I designed the logic of the system:

  • The system is a dedicated machine that launches tests on behalf of the user.
  • It starts all the loop logic and orchestrates the components inside the loops.
  • It provides input (prompts, context, usable tools) to the agents and takes their output (results, structured output, evidence, screenshots, reports), connecting them.
  • It also renders the UI and visualizes the loop runs and case run results, so the user can access them easily.

Advancing it and making it better

I advanced the proof of concept (PoC). The system worked and had potential for automating the testing work, but it was not enough to meet the actual requirements of staging environments such as dev and test.

Isolation. The work was built in a local environment, where I isolated the data state before each case run. But a web-deployed application could not be isolated directly. So I chose a detour: using random string IDs for every test run to keep the runs from affecting each other.

Evidence and logs. I let the agents leave evidence and logs of their work so I could optimize performance. They were helpful for finding bottlenecks in the agents' work, especially the agents' tool-calling logs.

Token consumption. The Tester Agent consumed too many tokens on routine work like logging in, agreeing to terms, and setting up a new workspace. It was a resource leak. I provided MCP tools and helper APIs (importable in the spec script) for the agent. They were designed as functions that do the setup, instead of reading screens and clicking buttons. As a result, token consumption decreased by half.

Designing the functions. I put a lot of effort into the design of those functions, both the MCP tools and the helper APIs. They should match general use cases, and their arguments should be the same as the user's input on the screen. If I let them take surrogate IDs as arguments, they would depend on the real implementation and would not describe the user's actions. There were also many options to consider for performance: how to implement them, what to open to the agents, and how to match the behavior of the MCP tools and the helper APIs.

It was not a golden path, but I hid the implementation details of the functions and opened only the interface contracts and descriptions to the agents, and I made their inputs the same as the UI inputs. They call the backend API instead of using the browser, to reduce the response time. The behaviors they do not cover are covered by test cases for the preconditions.

Model choice. Changing the Tester Agent's model affected the quality of the assertions in the spec scripts. I saw a trend: a less capable model wrote more flawed assertion blocks. But using a more capable one went over budget, so I needed to optimize.

  • I adopted a Validator Agent to review the output of the Tester Agents, and adjusted the balance between cost and quality.
  • I adopted a Curator Agent so the loop improves itself. When a case took many attempt rounds, the agent improved the instruction prompt about the screen and its locators for the next case loop run.

The Next Challenges

I've come across LangGraph, which supports building agent loops and integrating agents. I want to use it to develop a backend application.

Comments 0

Be the first to comment.