> For the complete documentation index, see [llms.txt](/llms.txt).
> A full single-fetch corpus is available at [llms-full.txt](/llms-full.txt).
---
title: Prompts
description: Manage prompt text as a first-class artifact, run it from Python or TypeScript, and keep production prompt versions tied to code.
last_verified: 2026-10-07
---



A **Prompt** is a managed LLM prompt that can be drafted and tested in AGNT5, then committed with your application code for production. Use Prompts when the prompt itself is an artifact you want to version, evaluate, and deploy, instead of burying instructions inside function bodies.

In development, a Prompt can resolve through AGNT5's prompt store so you can test drafts quickly. In production, AGNT5 resolves Prompts from files bundled with the deployed code artifact. That keeps production behavior reproducible: the code version and prompt version move together.



**Go:**

The managed Prompt artifact described on this page (`prompts/<id>.mdx`, versioning, runtime overrides) is available in the Python and TypeScript SDKs. In Go, keep prompt text as string constants or template files you manage, and pass the rendered text as `Messages` on `GenerateRequest`, as shown in [Use Prompts inside workflows](#use-prompts-inside-workflows). For caching, see [Prompt caching](/docs/build/prompt-caching.md).



---

## Run a Prompt



**Python:**

```python
from agnt5 import lm
from agnt5.lm import Prompt

response = await lm.generate(
    model="openai/gpt-6-luna",
    prompt=Prompt(
        id="support_reply",
        variables={
            "customer": {"name": "Ada"},
            "topic": "shipping",
        },
    ),
)

print(response.text)
```





**TypeScript:**

```typescript
import { LM } from "@agnt5/sdk";

const lm = LM.openai();

const response = await lm.generate({
  model: "openai/gpt-6-luna",
  prompt: {
    id: "support_reply",
    variables: {
      customer: { name: "Ada" },
      topic: "shipping",
    },
  },
});

console.log(response.text);
```




> `prompt` replaces inline `messages` for the call. If you provide a Prompt, do not also pass raw prompt text or message arrays for the same generation request.


---

## Commit a production Prompt

Create a prompt file under `prompts/<id>.mdx` in your application repo:

```mdx
---
id: support_reply
version: 3
version_id: 018f0000-0000-7000-8000-000000000003
model: openai/gpt-6-luna
variables:
  - customer.name
  - topic
response_format: text
---

<System>
You are a concise support agent.
</System>

<User>
Reply to {{customer.name}} about {{topic}}.
</User>
```

AGNT5 parses the front matter for routing and generation settings, then renders the body into ordered chat messages. The file's `model` applies to the call, and each `{{name}}` is replaced by the matching entry in `variables`, so pass a value for every variable the prompt uses. The body supports `<System>`, `<User>`, and `<Assistant>` blocks. If no block is present, the body is treated as a single user message.

Prompt resolution looks in this order. `AGNT5_PROMPT_OVERRIDE` and `AGNT5_PROMPTS_MANIFEST` each take a directory or a `.md` or `.mdx` file:

1. `AGNT5_PROMPT_OVERRIDE`
2. `AGNT5_PROMPTS_MANIFEST`
3. `prompts/<id>.mdx`
4. `prompts/<id>.md`
5. AGNT5 prompt-run API fallback for non-production draft and test workflows

Prompt files must be Markdown or MDX. AGNT5 does not load prompt text from `prompts.lock` or JSON files; prompts are meant to be readable authored artifacts.


> In production environments, the Prompt must be bundled with the deployed artifact. Missing Prompts fail closed and do not fall back to control-plane state.


---

## Select a version

Use `version` when constructing the Prompt object, or pass the SDK's version option for the call.



**Python:**

```python
response = await lm.generate(
    model="openai/gpt-6-luna",
    prompt=Prompt(id="support_reply", version="3"),
)
```





**TypeScript:**

```typescript
const response = await lm.generate({
  model: "openai/gpt-6-luna",
  prompt: { id: "support_reply", version: "3" },
});
```



Pass the version as a string. It can match either the prompt file's `version` or its `version_id`.

---

## Override runtime settings

Use runtime LLM overrides when you want to test the same prompt with a different model. This is useful in the Playground, experiments, and one-off comparisons because workflow code can stay unchanged.



**Python:**

```python
ctx.runtime.llm.model = "anthropic/claude-sonnet-4-5"

response = await lm.generate(
    model="openai/gpt-6-luna",
    prompt=Prompt(
        id="support_reply",
        variables={"topic": "shipping"},
    ),
)
```





**TypeScript:**

```typescript
ctx.runtime.llm.model = "anthropic/claude-sonnet-4-5";

const response = await lm.generate({
  model: "openai/gpt-6-luna",
  prompt: {
    id: "support_reply",
    variables: { topic: "shipping" },
  },
});
```



For workflows with multiple prompts, set prompt-specific overrides by prompt id:



**Python:**

```python
from agnt5 import LLMRuntimeOptions

ctx.runtime.prompts["draft"] = LLMRuntimeOptions(
    model="anthropic/claude-haiku-4-5-20251001",
)
ctx.runtime.prompts["review"] = LLMRuntimeOptions(
    model="anthropic/claude-sonnet-4-5",
)

await lm.generate(model="openai/gpt-6-luna", prompt=Prompt(id="classify"))
await lm.generate(model="openai/gpt-6-luna", prompt=Prompt(id="draft"))
await lm.generate(model="openai/gpt-6-luna", prompt=Prompt(id="review"))
```





**TypeScript:**

```typescript
ctx.runtime.prompts['draft'] = {
  model: 'anthropic/claude-haiku-4-5-20251001',
};
ctx.runtime.prompts['review'] = {
  model: 'anthropic/claude-sonnet-4-5',
};

await lm.generate({ model: 'openai/gpt-6-luna', prompt: { id: 'classify' } });
await lm.generate({ model: 'openai/gpt-6-luna', prompt: { id: 'draft' } });
await lm.generate({ model: 'openai/gpt-6-luna', prompt: { id: 'review' } });
```



The Prompt file remains the source of truth for prompt text. Runtime overrides only change model execution settings for the current run. Prompt-specific overrides win over the global runtime default.

---

## Use Prompts inside workflows

Prompts work anywhere you can call the language model SDK. Inside workflows, keep the LLM call inside a checkpointed step so replay can reuse the completed result.



**Python:**

```python
from agnt5 import function, FunctionContext, lm
from agnt5.lm import Prompt

@function
async def draft_reply(ctx: FunctionContext, customer_name: str, topic: str) -> str:
    response = await lm.generate(
        model="openai/gpt-6-luna",
        prompt=Prompt(
            id="support_reply",
            variables={
                "customer": {"name": customer_name},
                "topic": topic,
            },
        ),
    )
    return response.text
```

When this function is called through `ctx.step()` from a workflow, the generated reply is checkpointed with the rest of the step result.





**TypeScript:**

```typescript
import { fn, LM } from '@agnt5/sdk';
import type { Context } from '@agnt5/sdk';

const lm = LM.openai();

export const draftReply = fn('draft_reply').run(
  async (ctx: Context, input: { customerName: string; topic: string }) => {
    const response = await lm.generate({
      model: 'openai/gpt-6-luna',
      prompt: {
        id: 'support_reply',
        variables: {
          customer: { name: input.customerName },
          topic: input.topic,
        },
      },
    });
    return response.text;
  },
);
```

When a workflow calls this function through `ctx.step()`, the generated reply is checkpointed with the rest of the step result.





**Go:**

Keep the prompt text in your code, call `ctx.Generate` inside an `agnt5.Step`, and the result is checkpointed:

```go
const supportReplySystem = "You are a concise support agent."

err := agnt5.RegisterWorkflow(worker, "draft_reply", func(ctx *agnt5.Context, in DraftInput) (string, error) {
    return agnt5.Step(ctx, "draft_reply", func(context.Context) (string, error) {
        resp, err := ctx.Generate(model, agnt5.GenerateRequest{
            Messages: []agnt5.Message{
                {Role: agnt5.MessageRoleSystem, Content: supportReplySystem},
                {Role: agnt5.MessageRoleUser, Content: fmt.Sprintf("Reply to %s about %s.", in.CustomerName, in.Topic)},
            },
        })
        if err != nil {
            return "", err
        }
        return resp.Content, nil
    })
})
```



---

## Compatibility

Older SDK code may still use `PromptRef`, `prompt_ref`, or `promptRef`. Those names remain supported for compatibility, but new docs and new code should use **Prompt** as the concept:



**Python:**

```python
# Supported, but prefer prompt=Prompt(...)
await lm.generate(
    model="openai/gpt-6-luna",
    prompt_ref="support_reply",
    variables={"topic": "shipping"},
)
```





**TypeScript:**

```ts
// Supported, but prefer prompt: { id: "support_reply", variables: { ... } }
await lm.generate({
  model: "openai/gpt-6-luna",
  promptRef: { id: "support_reply", variables: { topic: "shipping" } },
});
```



Use `PromptRef` only when maintaining older code that already uses that terminology.

## Next steps

- [Prompt caching](/docs/build/prompt-caching.md): reuse a stable prompt prefix across calls.
- [Agents](/docs/build/agents.md): run prompts inside an agent loop.
- [Experiments](/docs/improve/experiments.md): compare prompt versions against a dataset.
