Articles / Viewpoints and methods
11 minFor tool users

Prompt Is Not Magic: Structured Output, Tool Calling, and Nondeterminism

Learn how prompt constraints, Structured Output, Tool Calling, temperature, top-p, and invariant-based testing turn an LLM into a more reliable AI application component.

Aaron HuangSystems, product and AI practice

Prompt Is Not Magic: Structured Output, Tool Calling, and Nondeterminism

In the previous article, we looked at Transformer, Attention, and Embeddings.

Once you understand those mechanisms, the next practical question is straightforward:

If an LLM is fundamentally predicting the next token, how do we make it behave reliably enough to build real applications?

The first answer many people reach for is:

Write a better prompt.

That is not wrong. It is simply incomplete.

A prompt can influence model behavior, but it cannot turn a probabilistic model into a conventional deterministic program.

Once AI moves from a chat interface into an application, the real engineering problems become broader:

  • How do we define the task and its constraints clearly?
  • How do we make model outputs machine-readable?
  • How should the model interact with external tools?
  • Why can the same input produce different outputs?
  • If outputs are inherently variable, how should we test the system?

This is one of the key transitions from using an LLM to engineering an AI application.

Prompt Thinking to System Thinking system diagram


1. What a Prompt Actually Does: It Narrows the Model's Choice Space

Prompt engineering is often presented like a collection of magic phrases.

Find the right wording, and the model suddenly becomes smarter.

From the model's perspective, however, the mechanism is much less mysterious.

At each step, an LLM estimates a probability distribution over possible next tokens based on the current context.

A prompt therefore provides additional conditions that make some outputs more plausible and others less plausible.

In other words:

A prompt is a mechanism for constraining the model's behavioral space.

Consider a vague instruction:

Analyze this product.

The model must infer almost everything:

  • Market analysis or feature analysis?
  • Competitor analysis?
  • How detailed should the answer be?
  • Who is the audience?
  • Should it make recommendations?
  • What should it do when information is missing?

Now compare it with:

You are a B2B Product Marketing Analyst. Based only on the product information below, analyze Target Customer, Pain Point, Value Proposition, and Competitive Differentiation. Give no more than three points per section. If the provided information is insufficient, return “insufficient information” instead of inventing an answer.

The second prompt leaves the model with a much smaller space of acceptable behavior.

Good prompts therefore tend to clarify four things.

Task

What exactly should the model do?

For example:

  • summarize
  • classify
  • extract
  • compare
  • reason
  • rewrite
  • generate

Context

What information does the model need in order to perform the task?

This might include:

  • background information
  • user requirements
  • documents
  • previous outputs
  • data returned by external systems

Constraints

What must the model do—or avoid doing?

For example:

  • use only the supplied information
  • return unknown when evidence is missing
  • stay under 300 words
  • use Traditional Chinese
  • return only specific fields

Output Contract

What form must the result take?

This becomes critical when the next consumer is not a human.

If the model is writing for a person, “roughly correct” may sometimes be good enough.

If another program must parse the result, however:

“Close enough” is often a failure.


2. Structured Output: Turning Language into Data

Suppose you want an LLM to classify a customer-support ticket.

For a human reader, this output may be perfectly acceptable:

Category: Refund
Priority: High
Requires human review: Yes

But if another system needs to process the result automatically, it may expect something like:

{
  "category": "refund",
  "priority": "high",
  "requires_human": true
}

To a person, these two outputs communicate almost the same information.

To software, they are very different interfaces.

That is the problem Structured Output is designed to solve.

Natural Language Is a Poor API Interface

LLMs are excellent at natural language.

Natural language, however, is highly variable.

A model might return:

Priority: High

or:

This request appears to be high priority.

or even:

{
  "priority": "urgent"
}

If the downstream application only accepts:

{
  "priority": "high"
}

semantic similarity is not enough.

For this reason, AI applications often constrain model outputs using a schema.

For example:

{
  "category": "billing | technical | account",
  "priority": "low | medium | high",
  "requires_human": true
}

This creates a kind of:

Model Output Contract

The model is no longer merely answering a question.

It is generating data that another system must be able to consume reliably.


3. Structured Output Is Not the Same as Saying “Return JSON”

A common mistake is to put this in the prompt:

Please output JSON.

The model returns valid-looking JSON, and the problem appears solved.

But that only solves the first layer.

A production system may still need to reason about several different forms of correctness.

Syntax Validity

Is the response valid JSON?

Schema Validity

Are the required fields present?

Are the types correct?

For example:

{
  "requires_human": "yes"
}

is valid JSON.

But if the application expects a Boolean:

{
  "requires_human": true
}

the output is still invalid for that application.

Modern model APIs may provide schema-constrained Structured Outputs that enforce this layer directly for supported schemas and configurations. That is stronger than ordinary JSON mode, which only guarantees valid JSON.

Semantic Validity

Even a perfectly valid schema can contain the wrong answer.

For example:

{
  "priority": "low",
  "requires_human": false
}

may be structurally perfect.

But if the user said:

My account was hacked and my credit card is being charged right now.

the problem is no longer formatting.

The model made the wrong judgment.

So:

Valid structure does not imply valid meaning.

Structured Output improves interface reliability.

It does not eliminate the need to evaluate what the model actually decided.


4. Tool Calling: The Model Does Not Need to Do Everything Itself

Suppose a user asks:

Do I have a meeting at 3 PM today?

The model does not inherently know what is on the user's calendar.

Without access to an external source, it can only:

  • use information already present in context, or
  • guess.

A better system can let the model decide:

I need calendar data.

It might produce a tool request conceptually similar to:

{
  "tool": "get_calendar_events",
  "arguments": {
    "date": "2026-09-21",
    "time": "15:00"
  }
}

The application or tool runtime executes the request.

The result is returned to the model.

The model can then answer:

You have a Project Review at 3 PM.

That is the basic idea behind Tool Calling.


5. The LLM Is Often the Tool Decision Maker, Not the Tool Executor

This distinction matters.

Architecture diagrams are often simplified into:

LLM → Tool

which makes it look as if the model itself is executing an API.

For custom tools, the real control flow is usually closer to:

User
 ↓
Application
 ↓
LLM
 ↓
Tool Request
 ↓
Application / Runtime
 ↓
External Tool or API
 ↓
Tool Result
 ↓
Application
 ↓
LLM
 ↓
Final Response

The model decides which tool it wants to use and produces the required arguments.

The surrounding runtime decides whether and how that tool is actually executed.

Some modern platforms also provide built-in tools whose execution is handled by the provider's runtime rather than by your own application code. The implementation differs, but the architectural distinction remains useful:

tool selection and tool execution are not the same responsibility.

Tool Calling therefore does not mean the model suddenly gained direct access to the outside world.

It means the model has been inserted into a software control loop.


6. The Hard Part of Tool Calling Is Often the Interface

Imagine giving a model this tool:

search(query)

That interface leaves many decisions unspecified.

The model must infer:

  • How specific should the query be?
  • Which language should it use?
  • Should it include a date?
  • Is it searching the public web or internal data?
  • How many results should it request?

Now compare it with:

search_documents(
  query: string,
  source: "internal" | "web",
  max_results: integer,
  date_after: date | null
)

The model's available choices are much clearer.

This follows the same principle as prompt constraints:

Do not rely on the model to guess correctly when the interface can encode the constraint directly.

Tool quality therefore depends on more than the model.

Tool names, descriptions, schemas, parameter definitions, and runtime validation all affect how reliably the system behaves.


7. Sampling: Why the Same Prompt May Not Produce the Same Answer

This introduces another major difference between LLM systems and conventional software:

generation is probabilistic.

At each token position, the model produces a probability distribution over candidate tokens.

Conceptually:

AI       0.38
model    0.21
system   0.17
agent    0.09
...

The generation process then needs a rule for selecting what comes next.

One option is to strongly favor the highest-probability token.

Another is to sample from multiple plausible candidates.

Once different tokens are selected early in the sequence, later generations may follow different paths.

That is one reason repeated runs can produce different outputs.

8. Temperature: Not a “Creativity Button”

Temperature is often explained as:

High temperature = creative
Low temperature = accurate

That is convenient, but imprecise.

A more useful interpretation is:

Temperature changes how concentrated the sampling distribution is.

Lower temperature tends to make high-probability candidates dominate more strongly.

Higher temperature makes lower-probability candidates relatively more likely to be selected.

Conceptually:

Lower temperature
→ narrower output distribution

Higher temperature
→ wider output distribution

This may look like “more conservative” versus “more diverse” behavior.

But temperature itself is not:

  • a factuality control
  • an intelligence control
  • a creativity detector

It is a sampling parameter.

And even low-temperature generation should not automatically be treated as perfectly deterministic.


9. Top-p: Restricting the Candidate Set

Another common sampling control is Top-p, also known as nucleus sampling.

Instead of sampling from the entire vocabulary, the system first keeps only enough high-probability tokens to reach a target cumulative probability.

Suppose the distribution is:

A  0.50
B  0.25
C  0.15
D  0.06
E  0.04

With top_p = 0.9, the candidate set may effectively stop after:

A + B + C = 0.90

The lower-probability candidates are excluded from that sampling step.

So, conceptually:

  • Temperature changes the shape of the sampling distribution.
  • Top-p changes how much probability mass is included in the candidate set.

Both influence the range and stability of possible outputs.


10. Why Traditional Unit-Test Thinking Is Not Enough

Traditional software can often be tested like this:

assert add(2, 2) == 4

Same input.

Same expected output.

Now imagine testing:

Input:
Summarize this customer complaint.

One run might return:

Customer requests a refund because the product arrived damaged.

Another might return:

The customer received a damaged product and is asking for a refund.

Both answers can be correct.

But this test:

assert output == expected_output

would reject the second answer.

This leads to an important shift in AI application testing:

We often need to test expected behavior rather than exact wording.


11. Test the Contract, Not Just the Sentence

Consider a support-ticket classifier.

Instead of requiring one exact string, we can test multiple properties.

Schema

Does the output contain the required fields?

{
  "category": "...",
  "priority": "...",
  "requires_human": true
}

Allowed Values

Is category restricted to:

billing
technical
account

Business Rules

If the user reports account compromise:

requires_human == true

Grounding

If the source data contains no order number, the model must not invent one.

Tool Behavior

If the task requires current order status, did the system use the order lookup tool instead of guessing?

These properties are often much more important than whether the final wording matches a reference answer character for character.


12. From Exact Match to Invariants

The difference can be summarized like this.

Traditional program:

Input
↓
Expected Exact Output

LLM application:

Input
↓
Range of Acceptable Outputs
↓
Required Invariants

An invariant is a property that must remain true even when the wording changes.

For example:

Do not invent missing data.
Return a valid required schema.
Escalate critical incidents.
Do not call undefined tools.
Tool arguments must match the tool contract.

These are the properties the application actually depends on.


13. Prompt Engineering Is Only One Layer

Putting the pieces together, a reliable LLM application does not place all of its trust in the prompt.

A more complete architecture looks like:

Prompt
↓
Constraints
↓
Structured Output
↓
Schema / Contract Enforcement
↓
Tool Interface
↓
Application Logic
↓
Evaluation

The prompt tells the model:

What behavior is expected?

Structured Output defines:

What shape must the result have?

Tool Calling defines:

What external capabilities can the model request?

Sampling explains:

Why can valid outputs vary between runs?

Testing answers:

How do we determine whether the system is still behaving correctly despite that variability?


14. The Real Transition: From Prompt Thinking to System Thinking

This is one of the most important distinctions for an AI Application Engineer.

When a beginner sees a bad model response, the first reaction is often:

Change the prompt.

Sometimes that is exactly the right fix.

But once the system becomes more complex, the better diagnostic questions are:

Is this really a prompt problem?
Or is the context insufficient?

Is the output unstable?
Or is the schema underspecified?

Does the model lack information?
Or should it have called a tool?

Is this normal sampling variation?
Or an actual regression?

Did the model fail?
Or is the surrounding system poorly designed?

At this point, we are no longer simply “using a model.”

We are engineering:

a software system that contains a probabilistic model.

And that leads directly to the next question.

Even if the prompt is clear, the output schema is valid, and the tool call succeeds:

Does that mean the AI system is reliable in production?

Not necessarily.

Real systems must also deal with:

  • model failure
  • retrieval failure
  • tool failure
  • validation
  • fallback behavior
  • observability
  • cost
  • latency
  • evaluation

Those are no longer just prompt-engineering problems.

They are Production AI Engineering problems.

That is where the next article begins.