# engineering

We deleted every intent regex from our agent after it read "launch" as a command

Calin Turcan · Published · 5 min read

We deleted every intent regex from our agent after it read "launch" as a command

In short: The model decides what the user meant, in typed fields, and deterministic code enforces it against what the tools actually did. Every time we let code guess intent, or let the model enforce its own limits, something broke in production.

Why this matters for agents that act

I'm building Gen-X, a chat-based agent that does sales and marketing work on a user's real accounts: lead search, email drafts, LinkedIn, calendars. Once an agent can change things in someone's accounts, a wrong guess costs real money or reputation. These are the mistakes that changed how I build it.

1. Never decide intent with a regex

We had a small guard that checked whether a request was a write by matching verbs. A user asked the agent to "find posts about the launch of OpenAI Dots". The regex matched "launch", overrode the planner's own read-only answer, and the step could never finish. The user got three duplicate replies.

That day we removed every keyword and regex intent check in the system. Now the planner model states intent as typed fields, such as whether the request changes anything, whether it is a retry, or a yes/no decision. Plain code only checks those fields against what the tools actually did. When the planner misreads a phrasing, we add that phrasing to a live eval suite instead of adding another rule.

2. Pass typed parameters to tools, not a JSON string

Our planner used to return tool inputs as one JSON string. Cheaper models broke the escaping as soon as a request listed around 30 company names. Switching to a flat, typed parameter object fixed it.

One more trap: some providers reject length limits in the schema, so we keep the provider schema plain and enforce the limits in code.

3. Don't make the user wait for a count

"POS suppliers in Atlanta" took 76 seconds to reply "About 9,761 match. How many?", and 65 of those seconds went into counting before we asked.

Now the agent starts the search right away, returns the first page of 50, and lets a background job repair or widen the filters against the real database. The user sees results arriving instead of a question.

4. When widening a search, never drop identity filters

When few results came back, our broadening step once dropped the company-name filter. The agent returned people who matched the job title but worked at unrelated companies.

Now the filters that say who you asked for are never relaxed. Only the descriptive ones can be loosened.

5. Check the permission mode at every layer

Each chat thread has a mode: Read Only, Draft, or Full Auto. A prompt instruction like "ask before sending" is not enough, because models drift.

The mode is checked in five places: the approval check, the tool executor, the step engine, the instructions, and any sub-agents the main agent hands work to. Read Only refuses every write at the executor, even internal ones that never had an approval step.

6. Fill side fields with a second, focused call

The planner was supposed to fill in company domains alongside the main plan. On the same 30-company request it got 18 right on one run and 0 on the next.

One small dedicated call after planning, allowed to answer "unsure", now gets 19 to 21 right every run.

The pattern behind all six

The model decides what the user meant, in typed fields, and deterministic code enforces it. Whenever we let code guess intent, or let the model enforce its own limits, something broke in production.

Gen-X is at genx-app.com if you want to see where this runs. I'm happy to go into any of these in the comments.

Gen-XProspect ScoutCampaign ManagerSocial AssistantInbox ManagerLinkedIn AssistantCreative AssistantLeads Manager

Your team is ready when you are.

Start with the crew, build your first team, and see what it gets done before tomorrow morning.

Get the desktop app: macOS (Apple silicon) · macOS (Intel) · Windows · Linux (.deb)