0Pricing
AI Prompt Engineering · Lesson

Plain Text vs Formatted Output

When to request clean plain text vs rich markdown output.

Plain Text vs Formatted Output is a free AI Prompt Engineering lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the AI Prompt Engineering learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

The Plain Text Case

Markdown formatting is powerful — but it is not always the right choice. Many real-world applications need clean, unformatted text where markdown symbols would appear as literal characters rather than rendered formatting.

Knowing when to ask for plain text is as important as knowing how to ask for rich formatting.

When Plain Text Is Required

Use plain text output when your environment does not render markdown:

  • Email copy: most email clients show raw asterisks
  • SMS and push notifications: no formatting support
  • Voice output: text-to-speech reads '** bold **' literally
  • CRM and help desk fields: many do not render markdown
  • API data processing: when the text will be stored or further processed
  • Legacy system input fields: plain text only
import anthropic

client = anthropic.Anthropic(api_key='sk-ant-your-key-here')

response = client.messages.create(
    model='claude-opus-4-5',
    max_tokens=200,
    messages=[{
        'role': 'user',
        'content': (
            'Write a 120-character push notification for a flash sale ending in 2 hours. '
            'Plain text only — no emojis, no markdown, no asterisks, no special characters. '
            'Must include: urgency, discount percentage (30%), and category (electronics). '
            'Output the notification text only — nothing else.'
        )
    }]
)
print(response.content[0].text)

Asking for Plain Text Explicitly

AI models default to markdown-heavy output in many contexts. To get truly plain text, you must say so explicitly and often name the specific symbols to avoid:

  • 'Plain text only — no markdown formatting'
  • 'No asterisks, no pound signs, no bullet symbols'
  • 'No headers, no bold, no lists — flowing prose paragraphs only'
  • 'Strip all formatting — output as if writing in Notepad'
import openai

client = openai.OpenAI(api_key='sk-your-key-here')

# Without plain text instruction — likely gets markdown
default_prompt = 'Explain what a webhook is in 100 words.'

# With explicit plain text instruction
plain_prompt = (
    'Explain what a webhook is in 100 words. '
    'Output format: plain text only. No markdown. No asterisks. No headers. '
    'No bullet points. Just continuous prose paragraphs.'
)

for label, prompt in [('DEFAULT (likely markdown)', default_prompt), ('EXPLICIT PLAIN TEXT', plain_prompt)]:
    response = client.chat.completions.create(
        model='gpt-4o', max_tokens=150,
        messages=[{'role': 'user', 'content': prompt}]
    )
    print(f'--- {label} ---')
    print(response.choices[0].message.content)
    print()

Plain Text for Email Copy

Email copywriting is one of the most common plain-text use cases. While some email clients support HTML formatting, AI-generated email copy should arrive as clean prose that a human editor can paste directly into an email client or CRM without cleanup.

Specify: 'Write the email body as plain text. No markdown. No asterisks for bold. No dashes for lists. Use numbered sentences or line breaks instead of lists.'

import anthropic

client = anthropic.Anthropic(api_key='sk-ant-your-key-here')

response = client.messages.create(
    model='claude-opus-4-5',
    max_tokens=300,
    messages=[{
        'role': 'user',
        'content': (
            'Write a 3-paragraph re-engagement email for inactive newsletter subscribers. '
            'Context: SaaS analytics tool, subscriber inactive for 60 days.\n'
            'Format requirements:\n'
            '- Plain text only — no asterisks, no pound signs, no bullet symbols\n'
            '- Paragraph 1: acknowledge absence, create curiosity\n'
            '- Paragraph 2: one new feature they missed\n'
            '- Paragraph 3: CTA with a direct link placeholder [LINK]\n'
            '- No subject line — body only'
        )
    }]
)
print(response.content[0].text)

Clean Prose Paragraphs

Beyond avoiding markdown symbols, 'clean prose' means structuring ideas as flowing sentences rather than fragmented bullet points.

Good prose:

  • Uses transition words to connect ideas (however, additionally, as a result)
  • Varies sentence length for rhythm
  • Groups related ideas into coherent paragraphs
  • Avoids starting every sentence with a noun

Request: 'Write in clean prose paragraphs — no lists, no headers, flowing sentences with transitions.'

import openai

client = openai.OpenAI(api_key='sk-your-key-here')

prose_prompt = (
    'Explain the advantages of using Docker for development environments. '
    'Write in 3 clean prose paragraphs. '
    'Requirements:\n'
    '- No bullet points or numbered lists\n'
    '- No markdown headers\n'
    '- Use transition words between sentences and paragraphs\n'
    '- Vary sentence length — mix short and long\n'
    '- 150 words total maximum'
)

response = client.chat.completions.create(
    model='gpt-4o',
    messages=[{'role': 'user', 'content': prose_prompt}]
)
print(response.choices[0].message.content)

Plain Text for Voice Output

Text-to-speech systems read everything literally. If your AI output will be spoken aloud:

  • Avoid all markdown symbols
  • Avoid abbreviations (TTS may not expand them)
  • Write out numbers in full when appropriate
  • Use commas for natural pause points
  • Avoid parentheses — TTS often reads them awkwardly
  • Spell out special characters ('@' → 'at')
import anthropic

client = anthropic.Anthropic(api_key='sk-ant-your-key-here')

response = client.messages.create(
    model='claude-opus-4-5',
    max_tokens=200,
    messages=[{
        'role': 'user',
        'content': (
            'Write a 45-second spoken weather briefing for London today. '
            'Conditions: 12 degrees Celsius, light rain, wind 15 km/h from the southwest.\n'
            'Format for voice output:\n'
            '- No markdown symbols of any kind\n'
            '- No parentheses\n'
            '- No abbreviations (write "kilometres per hour" not "km/h")\n'
            '- Natural spoken rhythm — use commas for pause points\n'
            '- Write numbers as words when under ten'
        )
    }]
)
print(response.content[0].text)

Stripping Markdown from Existing Output

Sometimes you get markdown output from one AI call and need to clean it for a different context. You can use a second AI call specifically for stripping:

'Remove all markdown formatting from the following text. Replace **bold** with plain text, remove # headers, convert bullet points to numbered sentences, remove all asterisks and pound signs. Output clean plain text only.'

import openai
import re

client = openai.OpenAI(api_key='sk-your-key-here')

markdown_text = (
    '## Key Benefits\n'
    '- **Faster deployment** with Docker containers\n'
    '- **Consistent environments** across dev and prod\n'
    '- Reduced *configuration drift* between machines\n'
    '### Getting Started\n'
    'Run docker-compose up to start all services.'
)

# Option 1: Ask AI to strip
response = client.chat.completions.create(
    model='gpt-4o',
    max_tokens=150,
    messages=[{
        'role': 'user',
        'content': (
            'Remove all markdown formatting from the text below. '
            'Keep all the information but strip: **, ##, ###, -, *, backticks. '
            'Convert bullet lists to flowing sentences. Output plain text only.\n\n'
            + markdown_text
        )
    }]
)
print('AI-stripped:', response.choices[0].message.content.strip())

# Option 2: Simple regex strip (for code-based pipelines)
import re
clean = re.sub(r'[#*]', '', markdown_text).strip()
print('Regex-stripped:', clean)

Plain Text in System Messages

For AI assistants that consistently output to plain-text environments, set the formatting rule once in the system message rather than repeating it in every user turn.

This is the cleanest approach for production applications where you know the rendering environment ahead of time.

import anthropic

client = anthropic.Anthropic(api_key='sk-ant-your-key-here')

# System message enforces plain text for all responses
plain_text_system = (
    'You are a helpful assistant embedded in a mobile push notification system. '
    'All your responses are displayed as plain text in mobile notifications. '
    'ALWAYS follow these formatting rules:\n'
    '- Never use markdown (no **, no #, no -, no backtick, no *, no _)\n'
    '- Never use bullet points or numbered lists\n'
    '- Write in 1-2 complete sentences only\n'
    '- Maximum 120 characters per response\n'
    '- No emojis'
)

response = client.messages.create(
    model='claude-opus-4-5',
    max_tokens=64,
    system=plain_text_system,
    messages=[
        {'role': 'user', 'content': 'Notify user their order has shipped and will arrive in 2 days.'}
    ]
)
print(response.content[0].text)

Formatting Decision Framework

Use this quick decision framework before requesting any output format:

  1. Where does the output go? Web UI, email, terminal, voice, database
  2. Does that environment render markdown? Yes → use markdown. No → plain text.
  3. Will a human read it? Yes → structure for scannability. No → optimize for parsing.
  4. Will code process it? Yes → JSON or CSV, no prose.
  5. Will it be spoken? Yes → voice-safe plain text, no abbreviations.
def choose_format(environment, human_reads, code_processes, voice_output):
    '''Simple formatting decision tree.'''
    if voice_output:
        return 'PLAIN TEXT — voice safe, spell out numbers and units'
    if code_processes:
        return 'JSON or CSV — machine-parseable, no prose'
    renders_markdown = environment in ['web', 'notion', 'github', 'vscode', 'obsidian']
    if renders_markdown and human_reads:
        return 'MARKDOWN — headers, bold, code blocks, lists'
    return 'PLAIN TEXT — clean prose paragraphs, no markdown symbols'

scenarios = [
    ('web',         True,  False, False),
    ('email',       True,  False, False),
    ('api_pipeline',False, True,  False),
    ('voice_app',   False, False, True),
    ('terminal',    True,  False, False),
]
for env, human, code, voice in scenarios:
    result = choose_format(env, human, code, voice)
    print(f'{env:<15} -> {result}')

Structured Plain Text

Plain text does not have to be unstructured. You can create structure without markdown using:

  • ALL CAPS SECTION LABELS (rendered equally anywhere)
  • Line breaks between sections
  • Numbered sentences: '1. First point. 2. Second point.'
  • Em dashes for separation: 'Key insight — always verify before acting.'
  • Consistent indentation using spaces (for terminal output)
import openai

client = openai.OpenAI(api_key='sk-your-key-here')

response = client.chat.completions.create(
    model='gpt-4o',
    messages=[{
        'role': 'user',
        'content': (
            'Write a daily briefing for a developer — 3 sections: TASKS, BLOCKERS, NOTES. '
            'Format: plain text only. '
            'Use ALL CAPS section labels followed by a colon. '
            'Use a line break between sections. '
            'Number each item within a section. '
            'No markdown symbols of any kind. '
            'Use realistic placeholder content.'
        )
    }]
)
print(response.choices[0].message.content)

Output Format Detection

In production applications, you can detect the output environment programmatically and inject the appropriate format instruction automatically — so you never need to specify it manually in each prompt.

This is a common pattern in multi-channel AI systems that serve the same content across web, mobile, and API consumers.

import anthropic

client = anthropic.Anthropic(api_key='sk-ant-your-key-here')

def get_format_instruction(channel):
    formats = {
        'web':   'Use markdown formatting: headers, bold, bullet points, code blocks.',
        'email': 'Plain text only. No markdown symbols. Use line breaks between sections.',
        'sms':   'Plain text. Single paragraph. Max 160 characters.',
        'voice': 'Plain text. No symbols. Natural spoken sentences only. Spell out numbers.',
        'api':   'JSON output only. No prose.',
    }
    return formats.get(channel, 'Plain text only.')

def ask_with_channel(question, channel):
    fmt = get_format_instruction(channel)
    response = client.messages.create(
        model='claude-opus-4-5',
        max_tokens=100,
        system=f'Format instruction: {fmt}',
        messages=[{'role': 'user', 'content': question}]
    )
    return response.content[0].text

q = 'What are 3 benefits of regular code reviews?'
for ch in ['web', 'sms', 'voice']:
    print(f'[{ch.upper()}]:')
    print(ask_with_channel(q, ch)[:150])
    print()

Knowledge Check

A developer builds an AI chatbot for customer service that feeds responses into a legacy CRM that stores plain text. The AI keeps outputting responses with ** for bold and - for bullets, which display as raw characters in the CRM. What is the most reliable fix?

Plain Text vs Formatted Output — Recap

Choosing the right format depends on your output environment. Key rules:

  • Use markdown when the environment renders it: web UIs, Notion, GitHub, docs
  • Use plain text for email copy, SMS, voice, CRMs, and API pipelines
  • Use JSON/CSV when code will process the output
  • Request plain text by explicitly listing what to avoid: no asterisks, no pound signs, no bullets
  • Set formatting rules once in the system message for consistent application behavior
  • Plain text can still have structure via CAPS LABELS, line breaks, and numbered sentences

Frequently asked questions

Is the “Plain Text vs Formatted Output” lesson free?

Yes — the full text of “Plain Text vs Formatted Output” is free to read here on the web, and the AI Prompt Engineering course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the AI Prompt Engineering course, upgrade to CoddyKit PRO.

What will I learn in “Plain Text vs Formatted Output”?

When to request clean plain text vs rich markdown output. You practise AI Prompt Engineering with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start AI Prompt Engineering?

No prior experience is required. AI Prompt Engineering on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Plain Text vs Formatted Output” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this AI Prompt Engineering lesson?

Yes. Every AI Prompt Engineering lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Requesting Lists and Bullet Points
  2. Asking for Tables and Structured Data
  3. Markdown Formatting in Prompts
  4. Plain Text vs Formatted Output
← Back to AI Prompt Engineering