DE Central: Halodoc’s AI Agent for Data, Pipelines, and Code

At Halodoc, AI has already changed the way we build and solve problems in software engineering. Data engineering is going through a similar shift. AI is starting to change how we work with data, pipelines, and the systems behind them.

We started building AI skills for things like configuring/creating pipelines, understanding alerts, and spotting data discrepancies. As more skills came in, we wanted an easier way for all our users across tech, product, marketing, and business to look at the data available in our Data Platform and make informed decisions with the help of AI. The end goal was faster decision-making based on existing data, without needing to decide which skill to use.

This led us to build DE Central at Halodoc, a central AI agent that makes the Data Platform easier to use for everyone. It can help diagnose pipeline failures, assist in development, answer data and catalog questions, pull ingestion numbers, and trace table usage across repositories. It's built on the AWS Lambda and accessible through Google Chat and Custom connectors of AI providers.

Background and Context

Three kinds of asks land on a data engineer/analyst's desk, and they behave differently.

Data questions. Which table holds refund data? Is it active or legacy? What feeds the payments dashboard? Can you pull these numbers? These need lineage, catalog lookups, safe query access, and data freshness.

Ops questions. A DAG failed, a Spark job died, a DMS task is stuck, a deployment is red. These need logs and a triage process.

Development questions. Where is this SQL defined? Which repos depend on this one? What are the testing conventions in this codebase? These need code search and repo context.

Our first attempt at solving this was to build individual AI skills for specific jobs like onboarding DataMart tables, exploring config tables, setting up reporting pipelines, reviewing SQL merge requests, and more. But as these skills multiplied, the same knowledge started getting duplicated, choosing the right skill became harder, and every skill came with its own tools and credentials to set up on each laptop.

That made the problem less about building another skill and more about having a central place that could bring the knowledge, tools, and controls together. That became the motivation for DE Central.

Design and Architecture

System Architecture

The whole agent runs as a single AWS Lambda: transport, authentication, the model loop and every tool execute in one function, invoked per request. Traffic comes in bursts rather than at a steady rate, so a server sized for the busy ten minutes sits idle for the rest of the day and Lambda matches this behaviour, scaling to zero between bursts and billing per question.

Agent being Serverless brings four properties, and most of the design follows from them:

Property Consequence
State lives outside the invocation S3 and DynamoDB hold everything durable
Temporary local storage per container Runtime and brain are fetched there on cold start
Runs are time-bounded Each run finishes inside its invocation, with time reserved to reply and log
Deployment packages are size-capped The large agent runtime is served from S3

Inside the Lambda, the runtime has three main responsibilities: transport (identify the caller, dispatch), agent core (load the brain, run the Claude Agent SDK loop against Bedrock), and read-only tools over Airflow, CloudWatch, EMR, DMS, Athena, Redshift/Metabase, GitLab, code search, Jenkins and the config database.

Two front doors, one core

Lambda URL serves both Gchat and MCP client, deciding from the request itself.
If the request comes from an MCP client, Lambda exposes its tools directly as an MCP server, and if the requests are from Google Chat they follow a separate flow through the Claude SDK, which uses the same underlying tools.

This also keeps model usage decentralized. Users connecting through MCP can use their own Claude access, while DE Central centralizes the tools, knowledge, permissions, and audit trail instead of routing every request through one shared model account.

Even though its Same brain, same tools for two doors, it has three core differences:

  • Toolset — the autonomous investigation pass belongs to chat. MCP clients expect fast tool calls, so they get the granular tools and drive the work themselves.
  • Reply — MCP answers in-band. Chat replies asynchronously: the bot posts the finished answer back into the original thread, since a real investigation outlasts the webhook. Just the answer, no tool narration.
  • Duplicates — chat webhooks retry, so each message is claimed once before work begins and repeats are dropped.

How a Question Flows

A question like "can you check AI cost of de-central" comes back with the total, a daily chart, and the table the numbers came from directly to claude.

DE Central answering a question asked from Claude about AI COST of a AI usecase

Behind it are four tool calls. Agent checks who's asking, works out where LLM cost lives, reuses the SQL from our existing AI COST card, then runs the query.

The same AI Cost question, traced: tool calls behind that answer and the table they read.

Authentication: owned by Cognito

An Amazon Cognito user pool owns authentication end to end, with Google sign-in federated into it. It stores the credentials, runs the sign-in and issues the tokens, so engineers authenticate with their Halodoc account and that exchange stays between the client and Cognito.

The Lambda acts purely as a resource server, with three jobs: publish where to authenticate, verify the token that arrives, and read user's email address. Enrolment, MFA, session lifetime and key rotation stay with Cognito.

Authorization: role-based tool access, kept as data

The email is where every caller converges. Lookup on access table returns the caller's role along with the tool patterns that role may use, and the runtime role matches against them.

Access table

Roles and their grants are maintained as rows in the config database, joined and flattened into one record per user by a sync job, so a request never joins anything and a permission change ships as data rather than a deployment. Grants are patterns an exact tool name, a prefix, or everything and a denial always beats an allow.

The same policy is then applied at three depths:

Depth What happens
Tool discovery The advertised tool list is filtered per caller, so nobody is offered a tool they can't use
Tool call An ungranted call is refused and recorded
Inside the agent Tools the caller lacks are removed from the agent's own toolset, and every call the agent makes is re-checked before it runs
The same controls also define what the agent should not expose. PII, raw data dumps, credentials, and other sensitive information are kept outside the agent's responses, even when the underlying systems contain them.

Keeping the Brain Outside the Agent

The agent runtime is larger than a Lambda package allows, so the brain lives in S3 and is fetched into temporary storage on cold start. With S3 already in the request path, syncing the agent's instructions from it followed naturally: the agent definition, skills, runbooks and knowledge base live in a separate repository and sync on every invocation.

  • Improving the agent is a file edit rather than a release.
  • Both front doors pick up the improvement at once.
  • The knowledge can be updated without a code deployment.

Persistence: one record per execution

Each invocation is designed to produce one request record: front door, user and role, outcome, duration, and the ordered list of tools called, including the ones the agent chose itself, which makes "what did it actually do" answerable afterwards.

On the MCP side there's an extra signal. Every externally-advertised tool takes a required context argument: a one-line, plain-language summary of what the user is trying to accomplish. The calling model fills it in as part of the call, so each invocation arrives with its own stated reason. A log of intent alongside the log of activity, which is what turns "this tool ran 40 times today" into something readable. Making the field required was the detail that mattered; as an optional argument, models skipped it and the context arrived empty.

Impact and Results

In the initial release to a limited group of users, it handled roughly 1,000–1,400 requests per day, with MCP accounting for almost all the volume at a 3.3s mean response time. GChat, which performs a full autonomous investigation per message, had a 75s mean response time for alert triage which previously took ~60 minutes of engineer time.

And the adoption has also moved beyond individual experiments. DE Central is now used as a common entry point for data, ops, and development questions across the Data Engineering team.

It has also changed two things at once, and they matter equally.

For data engineers, the ops loop got shorter. An alert now arrives in the thread with a first analysis attached , the DAG's recent runs, the actual task log, the failing job's state, so whoever picks it up starts from a hypothesis rather than a link and six browser tabs. In recent Data Warehouse data discrepancies, DE-CENTRAL accurately predicted the root cause in 70% of cases.

Sample request from GChat to DE-CENTRAL

For everyone else, data questions stopped needing a data engineer or a data/business analyst. "Which table holds refund data", "is this table active or legacy", "what feeds the payments dashboard" used to need someone's attention and, beyond a saved dashboard, their query access. With the help of DE-CENTRAL we could able to do analysis on data and create dashboards within a hour which used to take us more than 1 week.

What's Next

From flagging to fixing. Today the agent finds the cause when asked. The goal is for it to not need the ask: watch the system, flag what's wrong, raise the merge request with the fix. It already knows the failure catalogue and the deploy path, and an MR is the right output because a human still reviews and merges. We move from writing fixes to reviewing them.

A shared semantic layer. The agent currently maps a business term to the right table on demand, per question so it re-derives the same ground repeatedly, and two phrasings can take different routes. A maintained glossary of terms, canonical tables and agreed definitions turns that into a lookup: faster convergence, consistent answers, definitions reviewed in one place.

Mining the request log. Every request is stored, so the log maps where effort goes. Pipelines that fail repeatedly point at what to fix at the source; questions that keep recurring should become a dashboard or a playbook entry; slow tools and expensive queries show up in the timings.

Right model for the right task. Routine answering and authoring new skills have different quality bars. A cheaper model handles the volume, a stronger one the authoring.

Data contracts and quality. an answer grounded in a bad table is still a bad answer, so the next layer is checks on the data itself, not just on how it's reached.

From search to actionable insights. flag that some of this is built, and say it's a follow-up post rather than describing it thinly here.

Conclusion

There is a line of thinking in AI that kept coming back to us while building DE Central, its the idea from The Bitter Lesson: as models improve over time, general methods tend to outperform attempts to hardcode intelligence into the system.

That shaped how we built it. We don't want to hardcode how the agent should think or handle every possible case. Models will keep evolving, and doing that would leave the system stuck with today's assumptions.

Instead, we focused on the things that give the model leverage: the right tools, the right knowledge, and the right controls. The thinking stays with the LLM. As the models get better, Agents should get better with them without having to be rebuilt around every new model.

References

Join us

Scalability, reliability, and maintainability are the three pillars that govern what we build at Halodoc Tech. We are actively looking for engineers at all levels, and if solving hard problems with challenging requirements is your forte, please reach out to us with your resume at careers.india@halodoc.com.

About Halodoc

Halodoc is the number one all-around healthcare application in Indonesia. Our mission is to simplify and deliver quality healthcare across Indonesia, from Sabang to Merauke. Since 2016, Halodoc has been improving health literacy in Indonesia by providing user-friendly healthcare communication, education, and information (KIE). In parallel, our ecosystem has expanded to offer a range of services that facilitate convenient access to healthcare, starting with Homecare by Halodoc as a preventive care feature that allows users to conduct health tests privately and securely from the comfort of their homes; My Insurance, which allows users to access the benefits of cashless outpatient services in a more seamless way; Chat with Doctor, which allows users to consult with over 20,000 licensed physicians via chat, video or voice call; and Health Store features that allow users to purchase medicines, supplements and various health products from our network of over 4,900 trusted partner pharmacies. To deliver holistic health solutions in a fully digital way, Halodoc offers Digital Clinic services including Haloskin, a trusted dermatology care platform guided by experienced dermatologists.

We are proud to be trusted by global and regional investors, including the Bill & Melinda Gates Foundation, Singtel, UOB Ventures, Allianz, GoJek, Astra, Temasek, and many more. With over USD 100 million raised to date, including our recent Series D, our team is committed to building the best personalized healthcare solutions — and we remain steadfast in our journey to simplify healthcare for all Indonesians.