ollama-haskell: Industry-grade Haskell client for the Ollama API

This is a package candidate release! Here you can preview how this package release will appear once published to the main package index (which can be accomplished via the 'maintain' link below). Please note that once a package has been published to the main package index it cannot be undone! Please consult the package uploading documentation for more information.

[maintain] [Publish]

A type-safe, well-tested Haskell client for interacting with locally-running LLMs via the Ollama HTTP API. Supports chat, text generation, embeddings, model management, streaming via conduit, structured outputs, tool calling, and more.


[Skip to Readme]

Properties

Versions 0.1.0.0, 0.1.0.1, 0.1.0.2, 0.1.0.3, 0.1.1.3, 0.1.2.0, 0.1.3.0, 0.2.0.0, 0.2.1.0, 0.3.0.0, 0.3.0.1
Change log CHANGELOG.md
Dependencies aeson (>=2.0 && <3), base (>=4.17 && <5), bytestring (>=0.10 && <0.13), case-insensitive (>=1.2 && <1.3), conduit (>=1.3 && <1.4), conduit-extra (>=1.3 && <1.4), containers (>=0.6 && <0.9), hashable (>=1.4 && <1.6), http-client (>=0.6 && <0.8), http-client-tls (>=0.2 && <0.5), http-types (>=0.7 && <0.13), mtl (>=2.2 && <3), ollama-haskell, resourcet (>=1.3 && <1.4), retry (>=0.9 && <0.10), stm (>=2.5 && <3), text (>=2.0 && <3), time (>=1.11 && <2), unliftio-core (>=0.2 && <0.3) [details]
License MIT
Copyright 2024-2026 Tushar Adhatrao
Author Tushar Adhatrao
Maintainer tusharadhatrao@gmail.com
Category Web, AI, Network
Home page https://github.com/tusharad/ollama-haskell
Bug tracker https://github.com/tusharad/ollama-haskell/issues
Source repo head: git clone https://github.com/tusharad/ollama-haskell
Uploaded by tusharad at 2026-08-05T17:31:16Z

Modules

Flags

Manual Flags

NameDescriptionDefault
integration-tests

Build and run integration tests (requires running Ollama server)

Disabled

Use -f <flag> to enable a flag, or -f -<flag> to disable that flag. More info

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees


Readme for ollama-haskell-0.3.0.1

[back to package description]

ollama-haskell

Hackage MIT License

Industry-grade, feature-complete, modern Haskell client library for the Ollama local LLM engine.

Features


Installation

Add ollama-haskell to your .cabal file:

build-depends:
    base >= 4.17 && < 5
  , ollama-haskell >= 0.3.0.0

Or using Stack in package.yaml:

dependencies:
  - ollama-haskell >= 0.3.0.0

Quick Start (5 Lines)

import Data.List.NonEmpty (NonEmpty ((:|)))
import Data.Text.IO qualified as TIO
import Ollama

main :: IO ()
main = do
  client <- defaultClient
  res <- chat client $ chatRequest "qwen3.5:2b" (userMessage "Why is the sky blue?" :| [])
  case res of
    Left err   -> print err
    Right resp -> mapM_ (TIO.putStrLn . messageContent) (crMessage resp)

Streaming Responses with Conduit

Stream LLM responses token-by-token as they generate:

import Data.List.NonEmpty (NonEmpty ((:|)))
import Data.Text.IO qualified as TIO
import Ollama

main :: IO ()
main = do
  client <- defaultClient
  let req = chatRequest "qwen3.5:2b" (userMessage "Count from 1 to 5." :| [])
  
  -- Stream chunks directly into stdout or collect them
  chunks <- collectStream (chatStream client req)
  mapM_ (TIO.putStr . maybe "" messageContent . crMessage) chunks
  putStrLn ""

Function & Tool Calling

Define function signatures and let the LLM execute structured tool calls:

import Data.List.NonEmpty (NonEmpty ((:|)))
import Ollama

calculatorTool :: Tool
calculatorTool = Tool "function" $ FunctionDef
  { fnName = "add"
  , fnDescription = Just "Add two numbers"
  , fnParameters = Just (FunctionParameters "object" Nothing (Just ["a", "b"]) Nothing Nothing Nothing)
  , fnStrict = Just True
  }

main :: IO ()
main = do
  client <- defaultClient
  let req = (chatRequest "qwen3.5:2b" (userMessage "What is 40 + 2?" :| []))
        { chatTools = Just [calculatorTool] }
  res <- chat client req
  case res of
    Left err   -> print err
    Right resp -> print (crMessage resp)

Structured Outputs (JSON Schema DSL)

Enforce structured JSON output formats using SchemaBuilder:

import Data.Text.IO qualified as TIO
import Ollama
import Ollama.Types.Format.SchemaBuilder

personSchema :: Schema
personSchema = buildSchema $ emptyObject
  |+ ("name", JString)
  |+ ("age", JInteger)
  |! "name"

main :: IO ()
main = do
  client <- defaultClient
  let req = (generateRequest "qwen3.5:2b" "Generate a person profile.")
        { genFormat = Just (SchemaFormat personSchema) }
  res <- generate client req
  case res of
    Left err   -> print err
    Right resp -> TIO.putStrLn (grResponse resp)

Environment Variables & Configuration

Construct a client using environment variables (OLLAMA_HOST, OLLAMA_API_KEY):

main :: IO ()
main = do
  client <- clientFromEnv
  -- Automatically connects to OLLAMA_HOST with optional Authorization: Bearer header
  ...

Or configure custom retry policies and loggers:

customConfig :: OllamaClientConfig
customConfig = defaultConfig
  { configBaseUrl = "http://my-ollama-server:11434"
  , configTimeout = 120
  , configRetry   = ExponentialRetry 3 1 -- 3 retries with exponential backoff
  , configLogger  = Just (\level msg -> putStrLn $ "[" <> show level <> "] " <> show msg)
  }

main :: IO ()
main = withClient customConfig $ \client -> do
  ...

Documentation & SDK Comparison


License

MIT © 2024–2026 Tushar Adhatrao