Picks one value from a fixed set of choices with an LLM.
Gut presents the subject, question, and choices to the configured adapter. It then maps the adapter's answer back to the original Elixir value. It does not return a string copy of that value or create atoms from model output.
Examples
{:ok, true} =
Gut.feel(
"Please fix this today.",
"Does this convey time pressure?",
[true, false]
)Use descriptions when a choice needs more context:
{:ok, :billing} =
Gut.feel(
ticket,
"Which team should handle this?",
billing: "Payment, invoice, or refund problems",
technical: "Product defects or access problems",
other: "Anything else"
)Integer ranges are also valid choices:
{:ok, 4} = Gut.feel(messages, "How frustrated is the customer?", 1..5)A successful result means that the adapter returned a valid choice. It does not mean that the judgment is correct.
Set allow_unsure: true to offer uncertainty as a choice. Gut returns
{:ok, :unsure} if the adapter selects it. The adapter may still select a
choice when it should be unsure.
Subjects
Gut sends string subjects as plain text. It encodes all other subjects as
JSON. Derive Gut.Subject to control which struct fields the adapter receives
without changing the struct's general JSON representation:
defmodule Ticket do
@derive {Gut.Subject, only: [:subject, :body]}
defstruct [:subject, :body, :internal_notes]
endThis also works with structs defined by Ecto.Schema.
Gut treats the subject as untrusted data when it builds a prompt. This reduces accidental prompt confusion, but it does not prevent prompt injection.
Configuration
Configure an adapter as a module or a {module, options} tuple:
config :gut,
adapter: {Gut.ReqLLM, model: "anthropic:claude-haiku-4-5"}Pass :adapter to feel/4 or feel!/4 to replace the configured adapter for
one call:
Gut.feel(subject, question, choices,
adapter: {MyApp.Adapter, model: MyApp.Classifier}
)The call option takes precedence over application configuration. See
Gut.Adapter to implement an adapter.
Errors
Adapter and provider failures return {:error, %Gut.Error{}}. Use the error's
reason field for control flow and its cause field for logging. feel!/4
raises the same error instead.
Invalid local input raises ArgumentError before the adapter runs. This
includes invalid questions, choices, options, subjects, and adapter
configuration.
Summary
Functions
Asks the configured adapter to choose the value that best answers question.
Asks the configured adapter to choose a value and returns it directly.
Functions
@spec feel(term(), String.t(), list() | Range.t(), keyword()) :: {:ok, term()} | {:error, Gut.Error.t()}
Asks the configured adapter to choose the value that best answers question.
subject can be a string or any value that implements Jason.Encoder.
Structs can derive or implement Gut.Subject for a Gut-specific
representation. question must be a non-empty string.
choices must contain between 1 and 100 choices. It can be:
- a list of unique values;
- an integer range; or
- a keyword list with string descriptions.
Lists and ranges return the selected value. Keyword lists present each value as a description and return the selected key.
Options
:adapter- aGut.Adaptermodule or a{module, options}tuple. It replaces the adapter from the:gutapplication configuration for this call.:allow_unsure- adds an unsure choice whentrue. Gut returns{:ok, :unsure}if the adapter selects it. Defaults tofalse.
Adapter and provider failures return {:error, %Gut.Error{}}. Invalid local
input raises ArgumentError before the adapter runs.
Examples
Gut.feel(review, "What is the sentiment?", [:positive, :neutral, :negative])
#=> {:ok, :positive}
Gut.feel(ticket, "Which team should handle this?",
billing: "Payment or invoice problems",
technical: "Product or access problems"
)
#=> {:ok, :technical}
Gut.feel(messages, "How frustrated is the customer?", 1..5)
#=> {:ok, 4}
Asks the configured adapter to choose a value and returns it directly.
This function accepts the same arguments and options as feel/4. It returns
the selected value, including :unsure when enabled. It raises Gut.Error
for an adapter or provider failure. Invalid local input raises ArgumentError.
Examples
Gut.feel!(ticket, "Which team should handle this?",
billing: "Payment or invoice problems",
technical: "Product or access problems"
)
#=> :billing