> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fetchhive.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Run with Ruby SDK

> Invoke an agent from Ruby with the fetch_hive gem

Use the official `fetch_hive` gem when you want to send a message to an agent from Ruby. The SDK wraps the public [`POST /v1/agent/invoke`](../api-reference/invoke-agent) endpoint, handles authentication, supports streaming via a block, and accepts multimodal inputs.

## Installation

Add to your `Gemfile`:

```ruby theme={null}
gem "fetch_hive"
```

Then run:

```bash theme={null}
bundle install
```

Or install directly:

```bash theme={null}
gem install fetch_hive
```

The gem uses `faraday` under the hood and supports Ruby 3.0+.

## Authentication

Set the `FETCH_HIVE_API_KEY` environment variable to your workspace API key (the client reads it automatically):

```bash theme={null}
export FETCH_HIVE_API_KEY=fhk_...
```

```ruby theme={null}
require "fetch_hive"

client = FetchHive::Client.new
```

Or pass the key explicitly:

```ruby theme={null}
client = FetchHive::Client.new(api_key: "fhk_...")
```

See [API Keys](../workspace/api-keys) for how to create and rotate keys.

## Basic example

Send a message to an agent and read the final response:

```ruby theme={null}
require "fetch_hive"

client = FetchHive::Client.new

reply = client.invoke_agent(
  agent: "AGENT_UUID",
  message: "Summarize the latest AI infrastructure trends"
)

puts reply["response"]
```

See the [non-streaming response shape](../api-reference/invoke-agent#response).

## Method reference

| Keyword      | Type            | Required | Description                                                                                                       |
| ------------ | --------------- | -------- | ----------------------------------------------------------------------------------------------------------------- |
| `agent`      | `String`        | Yes      | The agent ID                                                                                                      |
| `message`    | `String`        | Yes      | The message you want to send                                                                                      |
| `thread_id`  | `String`        | No       | An arbitrary string identifying a persistent conversation thread                                                  |
| `messages`   | `Array<Hash>`   | No       | Caller-managed conversation history. Each item: `{ role: "user" \| "assistant" \| "system", content: String }`.   |
| `image_urls` | `Array<String>` | No       | HTTPS image URLs attached to the current `message` for multimodal inputs                                          |
| `user`       | `String`        | No       | Opaque caller identifier surfaced in [User Tracking](../user-tracking/overview)                                   |
| `metadata`   | `Hash`          | No       | Flat caller-defined metadata for audit and log filtering. See [Invoke metadata](../user-tracking/invoke-metadata) |

The SDK injects `streaming: false` for `invoke_agent`. To stream, use `invoke_agent_stream` (below).

## Handling the response

```ruby theme={null}
reply = client.invoke_agent(agent: "AGENT_UUID", message: "Hello")

puts reply["response"]      # final text
puts reply["model"]         # model identifier
puts reply["usage"]         # token usage breakdown
puts reply["request_id"]    # use this to look up the run in Logs
puts reply["tool_calls"]    # tool invocations made during the run
```

## Streaming

Use `invoke_agent_stream` to receive Server-Sent Events as they arrive. The method yields each parsed event hash to the block:

```ruby theme={null}
client.invoke_agent_stream(
  agent: "AGENT_UUID",
  message: "Summarize the latest AI infrastructure trends",
  thread_id: "user-456-support-session"
) do |chunk|
  case chunk["type"]
  when "response"
    print chunk["response"]
    $stdout.flush
  when "tool"
    puts "\nCalling tool: #{chunk['tool']}"
  when "usage"
    puts "\n\nUsage: #{chunk['usage']}"
  end
end
```

The stream yields the same event types documented in [Invoke Agent → Response](../api-reference/invoke-agent#response): `summary` (when auto-summarization fires), `reasoning`, `response`, `tool`, a final `usage` event, or an `error` event if the provider fails mid-stream.

If you omit the block, the method returns an `Enumerator` you can pass around:

```ruby theme={null}
enum = client.invoke_agent_stream(agent: "AGENT_UUID", message: "Hello")
enum.each { |chunk| handle(chunk) }
```

## Multi-turn conversations

### Persistent threads

Pass any string as `thread_id` and Fetch Hive will create the thread on the first call and resume it on subsequent calls with the same value:

```ruby theme={null}
client.invoke_agent(
  agent: "AGENT_UUID",
  message: "What are the main AI infrastructure trends right now?",
  thread_id: "user-456-support-session"
)

client.invoke_agent(
  agent: "AGENT_UUID",
  message: "Which of those trends have the most enterprise adoption?",
  thread_id: "user-456-support-session"
)
```

### Stateless history

Manage state yourself by passing the previous turns in `messages`. Fetch Hive uses the supplied history for context but does not persist it:

```ruby theme={null}
client.invoke_agent(
  agent: "AGENT_UUID",
  message: "Which of those trends have the most enterprise adoption?",
  messages: [
    { role: "user", content: "What are the main AI infrastructure trends right now?" },
    { role: "assistant", content: "Teams are focusing on evals, tool routing, and observability." }
  ]
)
```

## Multimodal inputs

Attach images to the current message with `image_urls`:

```ruby theme={null}
result = client.invoke_agent(
  agent: "vision-agent",
  message: "Describe this image",
  image_urls: ["https://example.com/photo.jpg"]
)
puts result["response"]
```

URLs must start with `https://`.

## Configuration

| Option     | Default                        | Description                     |
| ---------- | ------------------------------ | ------------------------------- |
| `api_key`  | `ENV["FETCH_HIVE_API_KEY"]`    | Bearer token from the dashboard |
| `base_url` | `https://api.fetchhive.com/v1` | Override the API base URL       |
| `timeout`  | `120`                          | Request timeout in seconds      |

```ruby theme={null}
client = FetchHive::Client.new(
  api_key: "fhk_...",
  base_url: "https://api.fetchhive.com/v1",
  timeout: 120
)
```

## Errors

Non-2xx responses raise a `RuntimeError` with the status code and body. Rescue them if you need to handle failures:

```ruby theme={null}
begin
  reply = client.invoke_agent(agent: "AGENT_UUID", message: "Hello")
rescue => e
  warn "Fetch Hive error: #{e.message}"
end
```

See [Errors and Rate Limits](../api-reference/errors-and-rate-limits) for status code meanings.

## Links

* [Gem on RubyGems](https://rubygems.org/gems/fetch_hive)
* [Source on GitHub](https://github.com/Fetch-Hive/ruby-sdk)

## Next steps

* [Run with API](./run-with-api) - The same flow with cURL
* [Run with Python SDK](./run-with-python-sdk)
* [Run with Node.js SDK](./run-with-nodejs-sdk)
* [Run with PHP SDK](./run-with-php-sdk)
* [Invoke Agent](../api-reference/invoke-agent) - Full endpoint reference
