# Handwave 👋
Handwave your problems away with LLMs.
Tired of trying to programmatically solve a problem that anyone could solve
just by looking at it? Handwave it:
```elixir
import Handwave.OpenAI
llm_if user_email, "looks suspicious?" do
{:error, :blocked}
else
create_user(user_email)
end
```
Wish your app could just tell user what to do with the error? Maybe it can:
```elixir
iex> llm_rewrite(
%Req.Response{status: 401, body: "session token expired"},
"Tell user what to do without technical details"
)
"Your session has expired. Please log in again to continue."
```
`String` module is too boring for you? I feel the same:
```elixir
iex> llm_rewrite("HelloWorld", "convert to kebab-case", model: "gpt-4.1-nano")
"hello-world"
```
Always wished Oban job would just do the right thing? I'm not here to judge:
```elixir
import Handwave.OpenAI
@impl Oban.Worker
def process(job) do
# do things
catch
kind, error ->
formatted = Exception.format(kind, error, __STACKTRACE__)
formatted
|> llm_route([:snooze, :cancel, :error], "Snooze if it makes sense to try later, cancel if it's a lost cause, otherwise just error")
|> case do
:snooze -> {:snooze, 60}
:cancel -> {:cancel, error}
_ -> {:error, formatted}
end
end
```
## Implementation
Handwave uses state-of-the-art, battle-tested, production-ready `InstructorLite`
library with a ✨comprehensive✨ test suite. It _does not_ abstract different LLM
providers from you, but comes with support for most popular providers and makes
it easy to add support for your provider of choice.
## Installation
Add `handwave` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:handwave, "~> 0.1.0"}
]
end
```
Put relevant api keys depending on what provider you want to use:
```elixir
config :handwave,
openai_key: "api_key",
anthropic_key: "api_key",
gemini_key: "api_key"
```
Use one of the existing providers (`Handwave.OpenAI`, `Handwave.Claude`,
`Handwave.Gemini`) or create your own.