# string literals — ordinary, verbatim and raw

> Three ways to write a string, all of them C#'s. The ordinary form processes escapes. The verbatim form (`@"…"`) processes none and may span lines, which is what regular expressions and Windows paths want. The raw form (`"""…"""`) processes none either, lets you write quotes plainly, and — for the multi-line shape — strips the closing delimiter's own indentation, so a block of prose lines up with the code around it without any of that alignment reaching the value.

<!-- id: types-string-literals · area: types · stability: stable · html: https://osysharp.com/reference/types/string-literals/ -->

## Summary        {#summary}

```osy syntax
var a = "line one\nline two";           // escapes processed
var b = @"C:\temp\report.csv";          // no escapes; "" is a literal quote; may span lines
var c = """He said "yes" and left.""";  // no escapes; quotes written plainly
```

Pick by what the text contains. Escapes are convenient until the text is full of backslashes; then `@"…"` is
clearer. Both get awkward once the text is a *paragraph* — which is what the raw form is for.

## Signature      {#signature}

| form | escapes | quotes inside | spans lines |
|---|---|---|---|
| `"…"` | processed (`\n`, `\t`, `\\`, `\"`, `\uXXXX`) | `\"` | no |
| `@"…"` | none | `""` | yes, verbatim — every leading space is kept |
| `"""…"""` | none | written plainly | yes, and the closing delimiter's indentation is stripped |

## Description    {#description}

### The raw form, single line   {#raw-single}
Everything between the delimiters, exactly:

```osy title="quotes inside, nothing escaped" syntax
var q = """He said "yes" and left.""";      // He said "yes" and left.
```

Open with more than three quotes when the text itself contains three:

```osy title="a longer fence when the text holds three quotes" syntax
var fence = """"a ``` and a """ inside"""";
```

The rule is that the closing delimiter is at least as long as the opening one, so the author picks a fence longer
than anything inside. Same as C#.

### The raw form, multi-line — and the indentation rule   {#raw-multi}
Put nothing but whitespace after the opening delimiter and the literal becomes multi-line. Then:

- the first newline and the last newline are **not** part of the value;
- **the closing delimiter's indentation is stripped from every line**.

That second rule is the whole reason the form exists. It lets a block of prose sit at the indentation of the code
around it while none of that indentation reaches the value:

```osy syntax
agent Auditor {
  Prompt = """
    You review expense claims.

    Meals are reimbursable up to 60 per person per day.
    """;
}
```

The value is `You review expense claims.\n\nMeals are reimbursable up to 60 per person per day.` — no leading spaces,
no blank first line, no trailing newline. Written as `@"…"` the same block would carry four spaces on every line
into the value, and written as concatenated `"…"` fragments it would not be readable as prose at all.

⚠ **A line indented LESS than the closing delimiter is a compile error**, not a partial strip. The alternative is a
value whose leading whitespace depends on where in the file it was written, which nothing downstream could report.
Line the text up with the closing delimiter, or move the delimiter left.

⚑ **A blank line is exempt.** It has no indentation to disagree with, and requiring some would mean trailing spaces
on every empty line of a paragraph.

### Why raw literals matter most for a prompt   {#why}
An [agent](https://osysharp.com/reference/agent/loop/)'s `Prompt` is the clearest case: it is prose, it is inherently multi-line, and it is the most
important text on the declaration. The instructions a model actually receives should be readable in the source that
supplies them.

## Examples       {#examples}

A multi-line prompt, and a verbatim path, in one app:

```osy title="raw-and-verbatim-strings" test app=string-literals
entity Note {
  [Required, MaxLength(4000)] string Body;
  security { allow read, create, update when IsAuthenticated; }
}

/// The multi-line raw form: indented with the code, and none of that indentation is in the value.
string Guidance() {
  return """
    Keep a note short.

    A note that needs headings is a document, and belongs somewhere else.
    """;
}

/// The single-line raw form — quotes written plainly, no escaping.
string Quoted() {
  return """She said "no" twice.""";
}

/// Verbatim: no escapes, so a backslash is a backslash.
string ExportPath() {
  return @"C:\exports\notes.csv";
}
```

## See also       {#see-also}
- [Every type, in one list](https://osysharp.com/reference/types/vocabulary/) — every built-in type in one list
- [Constant expressions](https://osysharp.com/reference/types/constant-expressions/) — where a compile-time constant is required
- [the agent loop (app.Agent, Loop)](https://osysharp.com/reference/agent/loop/) — the multi-line prompt this form was built for
