Why INGRA Failed and What I Built Instead
I wanted to give an LLM full access to my computer. Then I hit two walls I couldn't code around. One was technical. The other cost $3,000.
I wanted to give an LLM full access to my computer.
Not a chatbot. Not a wrapper around an API. A real agent — one that could read my emails, browse the web, run scripts, and actually do things on my behalf.
So I built INGRA.
The Dream
INGRA was my first serious attempt at function orchestration for LLMs.
The idea was simple: curate a library of callable functions, expose them via OpenAPI, and let the LLM decide which ones to invoke. Auto-generated Swagger docs. LangChain integration. A clean developer experience.
I built the function hub. The execution layer. The chat interface.
It worked.
Until it didn't.
Wall 1: Node VM Is a Lie
I sandboxed function execution inside Node's VM module. It felt safe. Isolated. Responsible.
But the abstraction leaked everywhere.
I couldn't launch a headless browser — the VM didn't have access to real system resources. I couldn't write to the filesystem without jumping through hoops. Every edge case required a workaround, and every workaround introduced fragility.
The harder I pushed, the more obvious the truth became:
Sandboxing was protecting me from the very capabilities I needed.
I wasn't building an agent. I was building a cage.
Wall 2: $3,000 for an OAuth Checkbox
I wanted INGRA to read my Gmail.
Not anyone else's email. Mine. On my machine. For my personal automation.
Google's OAuth scopes for email access require a security assessment. Annual cost: $3,000.
For a personal project.
I stared at the pricing page. Closed the laptop. Walked away.
That was the moment INGRA died.
The Question That Changed Everything
Weeks later, I found myself still thinking about it.
Not about INGRA specifically — but about the absurdity of the situation.
I can open Gmail in my browser. I can read my own emails. I can copy, forward, delete — anything I want. No one asks me to pay $3,000 for that privilege.
So why was I asking for permission to do what I could already do manually?
The answer was uncomfortable:
I had designed for permission instead of capability.
I was so focused on building a "proper" system — OAuth flows, sandboxed execution, clean API boundaries — that I forgot the simplest truth:
If I can do it, my agent should be able to do it too.
The Pivot
I started over.
No sandboxing. No OAuth dependency. No permission-seeking architecture.
The new system would run on a dedicated server — my server — with full system access. It would launch browsers, install npm packages, write files, execute shell commands.
It would be me, given a computer.
I called it VARGOS.
What VARGOS Does Differently
Every failure in INGRA became a design constraint in VARGOS:
| INGRA | VARGOS |
|---|---|
| Node VM sandboxing | Real system processes |
| OAuth-dependent | IMAP, browser automation, local control |
| Functions hardcoded inline | Separate vargos-functions repo |
| Brittle string interpolation | Structured JSON schemas (OpenAPI + MCP) |
| General-purpose agent | System-level orchestrator |
| Limited extensibility | Metadata-driven function discovery |
The core is built with NestJS, exposing both OpenAPI and MCP endpoints.
Functions live in their own repository. Each function has a .ts executable and a .json metadata file describing inputs, outputs, and purpose. The LLM reads the metadata, selects a function, provides structured arguments — and VARGOS executes it.
No gatekeepers. No $3,000 checkboxes.
Reading Gmail Without OAuth
Here's the punchline.
To read Gmail, VARGOS can:
-
Use IMAP with an App Password — Gmail supports this natively. No OAuth required. Python's
imaplibor Node'simap-simplehandles it. -
Automate the browser — Log in once manually, persist the session, let Playwright do the rest.
-
Parse local mail client cache — If Thunderbird is already syncing, just read the local
mboxfiles.
Every one of these approaches was available to me from day one.
I just couldn't see them because I was too busy designing a "proper" system.
The Real Failure
Looking back, INGRA didn't fail because of Node VM limitations or OAuth costs.
It failed because I designed for the system I thought I should build instead of the problem I actually had.
I wanted an agent that could do things. I built a platform that asked for permission.
The $3,000 fee was the best thing that happened to me.
It forced me to stop and ask: What am I actually trying to do here?
The answer was always the same.
If I can do it manually, my agent should be able to do it too.
VARGOS is that answer.
The Industry Caught Up
When I built INGRA, "tool calling" was an OpenAI-specific feature. You structured your functions their way, used their SDK, played by their rules.
Then the industry evolved.
Anthropic introduced MCP — the Model Context Protocol. A vendor-agnostic standard for connecting LLMs to external tools and data sources. Suddenly, the function orchestration problem I'd been solving in isolation had a shared specification.
VARGOS now exposes both OpenAPI and MCP endpoints. The same functions work with Claude, GPT, or any model that speaks the protocol.
This is the part of the journey I didn't expect: building something that could eventually replace me.
I'm a software engineer. I write code that solves problems. But I'm also building an agent that writes code, executes it, and iterates on the results.
At some point, the agent gets good enough that I become optional.
That's not a threat. It's the goal.
When things evolve, we evolve too — or we get left behind. I'd rather be the one building the thing that makes my old job obsolete than the one pretending the change isn't coming.
If You're Building Agents
Before you reach for OAuth, before you sandbox execution, before you design for what platforms want you to do — ask yourself:
What can I actually do right now, without permission?
The answer is usually more than you think.
Constraints aren't blockers. They're redirects.
INGRA taught me what I wanted.
VARGOS is what I built.