In the previous article, I wrote that one of the hardest parts of AI adoption was not the technology itself, but the process of building trust. You have to listen to the tacit knowledge held by the business, let people add context back to the candidates produced by AI, and show the revised result quickly enough for resistance to turn into questions.
One sentence kept staying with me during that process.
“What changes if we include that condition too?”
And there is a familiar answer many of us give.
“We’ll incorporate it and show you in next week’s demo.”
That used to sound perfectly normal. But in an AX project, that “next week” can become a much bigger bottleneck than it seems. If it takes a week to turn a question or a piece of experience into working behavior, the context of the conversation cools down with it.
At some point, I started thinking about PoC speed differently.
The question is not how quickly we can write code. It is how long it takes for an idea from the business to come back as something that actually runs.
What I wanted to reduce was not development time by itself. It was Feedback Latency.
The Model Was Not What Made My AI PoCs Slow
When people talk about building an AI PoC, the model is often the first thing that comes to mind. Which model should we use? How should we design the Prompt? Should we add RAG? Should this become an Agent? All of those questions matter.
But after building several PoCs, I found that much of the time was being consumed outside the model.
- Who is going to call this capability?
- How will authentication work?
- What form should the input take?
- Where will the execution environment live?
- What Context should be passed to the Agent?
- Which Tools should be allowed?
- What Schema should the result follow?
- If execution fails, where should it restart?
- Can the same capability be reused from Web, n8n, and Salesforce?
For the first PoC, you can simply wire everything together. You can do the same for the second. By the third, however, the pattern starts to feel different.
Rebuilding authentication, invocation, execution, state, and response formats starts to feel more wasteful than validating the business idea itself.

I do not think that means we should build a giant Agent Platform from day one. The rule I settled on was much simpler.
If I see the same part being built more than once, that is when I move it into a common execution layer.
For me, the first place this became obvious was the Coding Agent.
I Started Treating Codex CLI as an Execution Engine, Not Just a CLI
A Coding Agent such as Codex CLI is naturally useful from a terminal. It can read a repository, modify code, run commands, and inspect test results.
I initially used it in the obvious way. I would organize the idea in ChatGPT, hand the implementation task to Codex, and then inspect the result on the server or in the Web App. That alone made development much faster.
But as I kept changing PoCs while talking with the business, another question emerged.
“What if I stop running this CLI myself and let another system call it?”
I was not trying to build a fully autonomous Agent. I wanted to place the execution capabilities of a Coding Agent inside my existing development environment and use it as an execution engine that an Application could call when needed.
Human
↓
Codex CLI
↓
Application
↓
API Boundary
↓
Agent Runtime
↓
Codex CLI
Seen this way, remotely launching Codex is not the important part. The more important problem is creating a stable boundary so the Caller does not need to know how the Agent is implemented internally.
I Put a Thin API Boundary in Front of the CLI
The structure I used in the PoC was not particularly complicated.
- A Caller such as Web, n8n, or Salesforce invokes an HTTP API.
- FastAPI handles authentication and input validation.
- The Agent Runtime assembles the Context and Parameters needed for execution.
- Codex performs the Reasoning and execution work.
- The result is returned to the Caller through a consistent response contract.
FastAPI itself is not the point. The same role could be implemented in Node.js or another Runtime. What mattered to me was the separation of responsibilities, not the specific technology stack.
The Caller owns the business touchpoint.
Web handles user input and presentation. n8n handles workflow orchestration and integrations across systems. Salesforce carries CRM Records and the Context of the actual business user.
The API Boundary owns the contract.
It determines who may call the capability, whether the input is valid, which Context must be provided, and the format in which the result is returned.
The Agent Runtime owns execution.
It assembles the Model, Instructions, Tool profile, execution environment, and required Context, then runs the Agent.
Once those roles were separated, the question itself changed.
“What Context should Salesforce pass to the existing Agent Runtime?”
That sounds similar to “How do I run Codex from Salesforce?”, but from an implementation perspective, it is a very different question.

Separating the Caller from the Runtime Made PoC Work Feel More Like Assembly
The biggest change after creating a common execution layer was the starting point for a new Use Case.
Previously, every new PoC meant reconsidering authentication, building another model invocation path, wiring up Tools, and deciding on a response format.
Once the common Runtime existed, most new Use Cases started with three questions instead.
- What role should this Agent perform?
- What Context should the Caller provide?
- What Schema should the result follow?
In other words, I was no longer rebuilding the execution foundation. I was mostly defining what was different about this Use Case.
That does not mean I had built a finished platform. It means the unfinished PoC became much easier to change.
The UI can change while the Runtime stays the same. An n8n Workflow can be added without changing how the Agent executes. Salesforce can become a new Caller without requiring the Agent internals to be rewritten.
Lowering the cost of starting the next experiment. That was the state I wanted.
I Separated the Stable Runtime from the Variable Agent Definition
Once the execution layer is shared, another problem appears: different Use Cases need different kinds of Agents.
Some tasks only need a fast model, while others require stronger Reasoning. Some tasks can return free-form text, while others must follow a strict JSON Schema. An Agent that modifies a repository does not need the same Instructions as an Agent that analyzes documents.
If every one of those differences becomes an if branch in code, the common Runtime becomes contaminated with Use Case-specific logic again. I found it more useful to think of the execution configuration as three layers.
Stable Runtime
- authentication boundary
- execution boundary
- common context assembly
- state and result contract
- execution information required for logging and audit
Variable Agent Definition
- model
- reasoning level
- instructions
- output schema
- tool profile
Runtime Context
- user
- current record
- allowed scope
- business context
- input for the current request
Conceptually, the invocation contract can look like this.
{
"input": "Analyze the current opportunity and propose next actions.",
"runtime_context": {
"user_id": "005...",
"record_id": "006...",
"scope": ["opportunity", "account"]
},
"agent": {
"model": "...",
"reasoning": "...",
"instructions": "...",
"tool_profile": "sales-assistant"
}
}
This JSON is not a standard Schema from a specific product. It is simply the conceptual separation I use when designing an execution contract.
KEY TAKEAWAY. Do not collapse information the Application already knows and information the Agent must reason about into one undifferentiated bundle.
Not Everything Needed to Become a Parameter
There is an easy trap once you start thinking about reuse: you want everything to become configurable.
The Model becomes a Parameter. Tools become Parameters. State, Retry, and Permission become Parameters. Eventually, the foundation that was supposed to make PoCs faster turns into another Platform product you now have to build.
I found the same rule useful here.
Repeatedly changing values belong outside. Things that have only been needed once can stay where they are.
Model, Reasoning, Instructions, and Output Schema are worth externalizing because they tend to change across experiments. Abstracting the Runtime around hypothetical future Use Cases that do not exist yet can do the opposite and increase Feedback Latency again.
A common foundation for fast PoCs should not be the foundation with the largest number of capabilities. It should be the one that reduces the surface area that must change for the next experiment.
Then the Codex Harness Started Becoming Available as an API
As I was drafting this article, on September 10, 2026, OpenAI released the Agents API in public beta.
According to OpenAI, the Agents API exposes the harness and infrastructure used to run Codex through an API and manages execution-layer concerns such as long-running sessions, context management, tool use, and subagent orchestration. OpenAI’s official announcement
That does not mean OpenAI’s product implementation is the same as the API Boundary and Runtime I had already started building around Codex CLI in my own environment.
What matters for this discussion is the architectural direction: the UI used to work with an Agent and the Harness or Runtime that actually executes the Agent can be treated as separate layers.
A CLI, IDE, or Web UI does not have to be the Agent itself. If the execution layer can be addressed through an API, the Caller can focus more on the business Context and the result contract it needs.
But in an Enterprise environment, that does not finish the problem. If anything, making execution easier makes the next question more important.
The More Agentic the System Became, the More Deterministic Boundaries Mattered
It is useful when an Agent can select Tools and plan multiple steps on its own. But should the Agent also have to infer facts the Application already knows?
If a user is looking at an Opportunity in Salesforce, the Application already knows several things.
- who made the request
- which Record the user is viewing
- which organization and permission scope the user belongs to
- which data scope the user may access
- which executions are allowed
Those are not things an Agent should have to infer from natural language.
Context that can be determined should be supplied by the Application. Only uncertain judgment should be left to the Agent.
That shifted my attention away from “How many Tools should I give the Agent?” The more freedom the Agent receives, the clearer the control plane outside the Agent needs to become.
Agent
- intent interpretation
- reasoning
- planning
- candidate action selection
Application / Runtime
- identity
- current record
- scope
- permission
- execution guard
- state
- audit

This principle is not only about strengthening security.
If the Agent does not have to infer the user’s identity, current Record, and allowed execution scope every time, the Reasoning can become lighter as well. Deterministic values can be supplied directly as Tool-call arguments, reducing unnecessary exploration and repeated calls.
In that sense, Deterministic Control is not the opposite of Agentic behavior. It can be the foundation that lets the Agent concentrate on the problems that genuinely require judgment.
What I Built Was a Feedback Loop, Not a Remote Codex API
The original question was simple: “Can I call Codex CLI from another system?”
But after building it, I realized that remotely launching the CLI was not what I actually needed. I needed a Feedback Loop that shortened the time between a question from the business, working behavior, another review, and the next change.
A Coding Agent does not have to remain a tool used directly by a person. If the Caller is separated from the Agent Runtime, the same execution foundation can be reused across very different business touchpoints such as Web, n8n, and Salesforce.
Separating the Stable Runtime from the Variable Agent Definition reduces the amount that must change for a new PoC. And the more work the Agent is allowed to perform, the more explicitly the Application should own Context and control responsibilities that can be determined in advance.
The thing I was really trying to shorten was the time it took for a question from the business to come back as working behavior.
As I wrote in the previous article, a PoC does not have to end with proving technical feasibility. It can become a conversation tool through which the business and the system learn to understand each other.
That makes the role of a good execution foundation much clearer.
Keep that conversation from breaking.
And that leaves the next question.
How much Tool execution should we delegate to the Agent, and where should deterministic Application control begin?
In the next article, I want to go deeper into that boundary: how to avoid over-atomizing Tools without nesting unnecessary Agentic decisions inside the Agent, and how the Caller can provide Runtime Context such as user, record, and scope before execution begins.