# `tag`: name every label that fits.

*The message praises the dashboard, reports a crash, and names a double charge. It gets praise, bug, and billing.*

```
question="Which labels fit this message?"
labels=(
  praise
  bug
  billing
)

cat <<'EOF' |
Love the new dashboard, but export crashes the app,
and I was charged twice.
EOF
thinkthen tag "$question" "${labels[@]}"
```

*Output*

```
["praise","bug","billing"]
```

*exit 0: the run finished*

You give it one question, one piece of evidence, and 1 to 20 labels. You get back the labels that fit, as a list.

## Read the answer

A label under the threshold is left out. An empty list is a good answer and exits 0.

| Exit code | What it means |
| --- | --- |
| 0 | the run finished |
| 2 | usage or input error |
| 4 | the backend failed or refused, as it does for evidence over the size limit |
| 5 | a local failure |
| 70 | a defect in the tool |

## Call it from your language

The Bash example opens this page.

```
import thinkthen as tt

question = "Which labels fit this message?"
labels = ["praise", "bug", "billing"]
message = (
    "Love the new dashboard, but export crashes the app,\n"
    "and I was charged twice.\n"
)
fitting_labels = tt.tag(
    question, message, labels=labels
).value
assert fitting_labels == ["praise", "bug", "billing"]
```

No Polars sample for `tag`.

No pandas sample for `tag`.

```
import assert from "node:assert/strict";
import * as tt from "thinkthen";

const question = "Which labels fit this message?";
const labels = ["praise", "bug", "billing"];
const message =
  "Love the new dashboard, but export crashes the app,\n" +
  "and I was charged twice.\n";
const fittingLabels = (await tt.tag(
  question,
  message,
  { labels },
)).value;
assert.deepEqual(fittingLabels, [
  "praise",
  "bug",
  "billing",
]);
```

No Ruby sample for `tag`.

```
library(thinkthen)

question <- "Which labels fit this message?"
labels <- c("praise", "bug", "billing")
message <- paste0(
  "Love the new dashboard, but export crashes the app,\n",
  "and I was charged twice.\n"
)
fitting_labels <- tt_tag(
  question, message, labels
)$value[[1]]
stopifnot(identical(
  fitting_labels,
  c("praise", "bug", "billing")
))
```

```
use thinkthen::{Engine, Question};

thinkthen::choices! {
    enum Label {
        Praise => "praise",
        Bug => "bug",
        Billing => "billing",
    }
}

let tt = Engine::from_env()?;
let question = "Which labels fit this message?";
let labels = Question::tag::<Label>(question)?
    .label(Label::Praise, None)?
    .label(Label::Bug, None)?
    .label(Label::Billing, None)?
    .cut()?;
let message = concat!(
    "Love the new dashboard, ",
    "but export crashes the app,\n",
    "and I was charged twice.\n",
);
let fitting_labels = tt.tag(&labels, message)?.into_value();
let expected = [Label::Praise, Label::Bug, Label::Billing];
assert_eq!(fitting_labels, expected);
```

Put this code inside `fn main() -> Result<(), Box<dyn std::error::Error>>` and end it with `Ok(())`. `main` returns a `Result`, so `?` compiles.

```
#include <assert.h>
#include <json-c/json.h>
#include <thinkthen.h>

thinkthen_engine *tt = thinkthen_engine_new();
assert(tt);

const char *tag =
    "{\"tag\": \"Which labels fit this message?\", "
    "\"labels\": [\"praise\", \"bug\", \"billing\"], "
    "\"evidence\": \"Love the new dashboard, but export "
    "crashes the app,\\nand I was charged twice.\\n\"}";
const char *expected = "[\"praise\",\"bug\",\"billing\"]";
char *tag_call = thinkthen_call(tt, tag);
assert(tag_call);
enum json_tokener_error parse_error;
struct json_object *result =
    json_tokener_parse_verbose(tag_call, &parse_error);
assert(parse_error == json_tokener_success);
assert(result && json_object_get_type(result)
    == json_type_object);
struct json_object *value;
json_bool has_value = json_object_object_get_ex(
    result, "value", &value);
assert(has_value);
struct json_object *facts;
json_bool has_facts = json_object_object_get_ex(
    result, "facts", &facts);
assert(has_facts);
assert(facts && json_object_get_type(facts)
    == json_type_object);
struct json_object *wanted =
    json_tokener_parse_verbose(expected, &parse_error);
assert(parse_error == json_tokener_success);
assert(json_object_equal(value, wanted));
if (wanted) json_object_put(wanted);
json_object_put(result);
thinkthen_free_string(tag_call);
thinkthen_engine_free(tt);
```

Keep the `#include` lines on top. Put the rest inside `int main(void)` and end it with `return 0;`.

No C++ sample for `tag`.

No Objective-C sample for `tag`.

No COBOL sample for `tag`.

No Ada sample for `tag`.

No Java sample for `tag`.

No Kotlin sample for `tag`.

No Scala sample for `tag`.

No C# sample for `tag`.

No Go sample for `tag`.

No Swift sample for `tag`.

No Zig sample for `tag`.

No PHP sample for `tag`.

No Dart sample for `tag`.

```
LOAD './thinkthen.duckdb_extension';

SELECT thinkthen_tag(
    'Which labels fit this message?',
    'Love the new dashboard, but export crashes ' ||
    'the app,' || chr(10) ||
    'and I was charged twice.' || chr(10),
    ['praise', 'bug', 'billing']
) AS fitting_labels;
```

*What DuckDB printed*

```
fitting_labels
[praise, bug, billing]
```

No SQLite sample for `tag`.

```
SELECT thinkthen_tag(
    '{"tag": "Which labels fit this message?",
      "labels": ["praise", "bug", "billing"]}',
    'Love the new dashboard, but export crashes ' ||
    'the app,' || chr(10) ||
    'and I was charged twice.' || chr(10),
    NULL
) AS fitting_labels;
```

*What PostgreSQL printed*

```
    fitting_labels    
----------------------
 {praise,bug,billing}
(1 row)
```

[Arguments, options, and more examples](/reference/functions/tag/)

## Jobs that use `tag`

- [Sort survey answers by mood and problem](/how-tos/code-open-ended-survey-answers/): for survey and market researchers

Watch `tag` answer questions about Beatles songs: [tag applies labels to data.](/learn/beatles-bench/tag/)

On GitHub: [github.com/botassembly/thinkthen](https://github.com/botassembly/thinkthen)
