langchain-hs: Pure functional LLM agent framework and multi-agent graph engine in Haskell

[ ai, library, mit ] [ Propose Tags ] [ Report a vulnerability ]

Build LLM-powered applications, ReAct agents, and LangGraph-style stateful workflows in Haskell. Provider-specific packages: - langchain-hs-ollama - langchain-hs-openai - langchain-hs-gemini - langchain-hs-mcp


[Skip to Readme]

Modules

[Index] [Quick Jump]

  • Langchain
    • Langchain.Agent
      • Langchain.Agent.PlanAndExecute
      • Langchain.Agent.ReAct
    • Langchain.Cache
      • Langchain.Cache.Core
    • Langchain.Callback
      • Langchain.Callback.Manager
    • Langchain.Chain
      • Langchain.Chain.RetrievalQA
    • Langchain.DocumentLoader
      • Langchain.DocumentLoader.Core
      • Langchain.DocumentLoader.DirectoryLoader
      • Langchain.DocumentLoader.FileLoader
    • Langchain.Embeddings
      • Langchain.Embeddings.Core
    • Langchain.Error
    • Graph
      • Langchain.Graph.Checkpointer
      • Langchain.Graph.HITL
      • Langchain.Graph.StateGraph
    • Langchain.Guardrail
      • Langchain.Guardrail.Core
    • Langchain.Memory
      • Langchain.Memory.Combined
      • Langchain.Memory.Core
      • Langchain.Memory.Entity
      • Langchain.Memory.Session
      • Langchain.Memory.Summary
    • Langchain.Model
      • Langchain.Model.Types
    • Langchain.Monad
    • Langchain.Observability
    • Langchain.OutputParser
      • Langchain.OutputParser.Core
      • Langchain.OutputParser.Structured
    • Langchain.Prelude
    • Langchain.PromptTemplate
      • Langchain.PromptTemplate.Prompt
      • Langchain.PromptTemplate.String
    • Langchain.Resilience
      • Langchain.Resilience.CircuitBreaker
      • Langchain.Resilience.Retry
    • Langchain.Retriever
      • Langchain.Retriever.BM25
      • Langchain.Retriever.Core
      • Langchain.Retriever.Hybrid
    • Langchain.Runnable
    • Langchain.Stream
    • TextSplitter
      • Langchain.TextSplitter.Character
      • Langchain.TextSplitter.Code
      • Langchain.TextSplitter.Markdown
      • Langchain.TextSplitter.RecursiveCharacter
      • Langchain.TextSplitter.Token
    • Langchain.Tool
      • Langchain.Tool.Binding
      • Langchain.Tool.Checkpoint
      • Langchain.Tool.Core
      • Langchain.Tool.FileSystem
      • Langchain.Tool.GenericSchema
      • Langchain.Tool.Process
      • Langchain.Tool.Security
      • Langchain.Tool.Shell
    • Langchain.VectorStore
      • Langchain.VectorStore.Core
      • Langchain.VectorStore.InMemory

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

  • No Candidates
Versions [RSS] 0.0.1.0, 0.0.2.0, 0.0.3.0, 0.0.5.0, 0.0.6.0
Change log CHANGELOG.md
Dependencies base (>=4.17 && <5), langchain-hs-core (>=0.0.6 && <0.0.7), langchain-hs-graph (>=0.0.6 && <0.0.7) [details]
Tested with ghc ==9.12.4, ghc ==9.10.3, ghc ==9.8.4
License MIT
Copyright 2025-2026 Tushar Adhatrao
Author Tushar Adhatrao
Maintainer tusharadhatrao@gmail.com
Uploaded by tusharad at 2026-10-14T21:34:37Z
Category AI
Home page https://github.com/tusharad/langchain-hs#readme
Bug tracker https://github.com/tusharad/langchain-hs/issues
Source repo head: git clone https://github.com/tusharad/langchain-hs
Distributions
Downloads 178 total (20 in the last 30 days)
Rating 2.0 (votes: 2) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs uploaded by user
Build status unknown [no reports yet]

Readme for langchain-hs-0.0.6.0

[back to package description]

LangChain Haskell (langchain-hs)

Type-Safe AI Agents & Multi-Agent Graphs in Haskell

A functional, effect-polymorphic Haskell ecosystem for building production AI applications, featuring pure AST pipelines (RunnableTree), cyclic state graphs (StateGraph), Model Context Protocol (MCP), and OpenTelemetry observability.

Hackage GHC License: MIT Documentation


Installation

Install langchain-hs and provider packages via Cabal:

cabal update
cabal install langchain-hs langchain-hs-ollama langchain-hs-openai

Or add to your stack.yaml:

extra-deps:
  - langchain-hs-0.0.6.0
  - langchain-hs-core-0.0.6.0
  - langchain-hs-graph-0.0.6.0
  - langchain-hs-ollama-0.0.6.0
  - langchain-hs-openai-0.0.6.0

Package reference on Hackage: https://hackage.haskell.org/package/langchain-hs


1. Simple Chat Calling

Send a prompt to an LLM (local Ollama, OpenAI, or Gemini) and retrieve a typed response:

{-# LANGUAGE OverloadedStrings #-}
module Main where

import Control.Monad.Except (runExceptT)
import qualified Data.Text.IO as T
import Langchain.Prelude
import Langchain.Provider.Ollama

main :: IO ()
main = do
  -- Connect to local Ollama instance (DeepSeek, Llama 3, Gemma, etc.)
  model <- newOllama "llama3.2" defaultConfig
  
  let messages = [userMessage "Explain in two sentences why Haskell makes AI agents more reliable."]
  result <- runExceptT $ invoke model messages Nothing
  
  case result of
    Left err   -> T.putStrLn $ errorMessage err
    Right resp -> T.putStrLn $ extractMessageText resp

Output

Haskell's static type system prevents common agent failures like missing dictionary keys or unexpected nulls before code ever reaches production. Furthermore, pure state transitions guarantee that autonomous agents cannot silently mutate variables behind your back.

2. JSON Structured Output

Guarantee that the LLM response conforms to a typed Haskell record using FromJSON and ToSchema:

{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}
module Main where

import Data.Aeson (FromJSON)
import qualified Data.Text as T
import qualified Data.Text.IO as T
import GHC.Generics (Generic)
import Langchain.Prelude
import Langchain.Provider.Ollama

-- Define your target data schema
data Developer = Developer
  { name              :: T.Text
  , preferredLanguage :: T.Text
  , yearsOfExperience :: Int
  , favoriteLibrary   :: T.Text
  } deriving (Show, Generic, FromJSON, ToSchema)

main :: IO ()
main = do
  model <- newOllama "llama3.2" defaultConfig
  
  let prompt =
        [ userMessage "Extract profile: Alan has been writing Haskell for 8 years and loves langchain-hs." ]
      options = withStructuredOutput (Proxy @Developer) defaultOllamaConfig

  result <- runLangchainT () $ invoke model prompt (Just options)
  case result of
    Left err  -> T.putStrLn $ errorMessage err
    Right msg -> T.putStrLn $ extractMessageText msg

Output

{
  "name": "Alan",
  "preferredLanguage": "Haskell",
  "yearsOfExperience": 8,
  "favoriteLibrary": "langchain-hs"
}

3. Tool Calling

Equip models with effectful Haskell tools. The LLM automatically emits structured tool calls, which your application executes and feeds back for final synthesis:

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}
module Main where

import Control.Monad.IO.Class (liftIO)
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Langchain.Prelude
import Langchain.Provider.Ollama

main :: IO ()
main = do
  model <- newOllama "qwen2.5:7b" defaultConfig
  
  -- Instantiate typed filesystem tool
  let fsTool   = findFilesTool @IO defaultSecurityPolicy
      toolCfg  = withTools [fsTool] defaultOllamaConfig
      prompt   = [userMessage "Search for Haskell source files using find_files with pattern '*.hs'."]

  res <- runLangchainT () $ do
    response <- invoke model prompt (Just toolCfg)
    case messageToolCalls response of
      Just (tCall:_) -> do
        liftIO $ T.putStrLn $ "Tool Invoked: " <> toolCallName tCall
        liftIO $ T.putStrLn $ "Arguments:    " <> T.pack (show (toolCallArguments tCall))
        
        -- Execute tool with LLM arguments
        execResult <- liftIO $ toolExecute fsTool (toolCallArguments tCall)
        let observation = case execResult of
              Left err  -> "Error: " <> errorMessage err
              Right out -> out
        liftIO $ T.putStrLn $ "Observation:  " <> observation
        
        -- Supply tool observation back to model for final response
        let toolMsg = (toolMessage observation) { messageName = Just (toolCallName tCall) }
            thread  = prompt ++ [response, toolMsg]
            
        finalMsg <- invoke model thread (Just toolCfg)
        liftIO $ T.putStrLn "\nFinal Assistant Answer:"
        liftIO $ T.putStrLn $ extractMessageText finalMsg
      _ -> do
        liftIO $ T.putStrLn $ extractMessageText response

  case res of
    Left err -> T.putStrLn $ "Error: " <> errorMessage err
    Right () -> pure ()

Output

Tool Invoked: find_files
Arguments:    fromList [("pattern",String "*.hs")]
Observation:  ["src/Main.hs","src/Agent.hs","src/Tools.hs"]

Final Assistant Answer:
I scanned the repository and identified 3 Haskell source files matching your pattern:
- src/Main.hs
- src/Agent.hs
- src/Tools.hs

4. ReAct Agent

Run an autonomous Reason + Act agent loop that decomposes user tasks, selects tools, evaluates observations, and iterates until completion:

{-# LANGUAGE OverloadedStrings #-}
module Main where

import Control.Monad.Except (runExceptT)
import qualified Data.Text.IO as T
import Langchain.Prelude
import Langchain.Provider.Ollama

main :: IO ()
main = do
  -- Setup sample file for demonstration
  writeFile "/tmp/server_status.txt" "Service: api-gateway, Status: Degraded, Latency: 420ms"
  
  model <- newOllama "qwen2.5:7b" defaultConfig
  
  -- Equip agent with file inspection tools
  let policy = defaultSecurityPolicy
      tools  = [readFileTool Nothing policy, findFilesTool policy]
      agent  = defaultReActAgent model tools
      prompt = [userMessage "Inspect /tmp/server_status.txt using read_file and summarize the service health."]

  res <- runExceptT $ runReActAgent agent prompt
  case res of
    Left err  -> T.putStrLn $ errorMessage err
    Right msg -> T.putStrLn $ extractMessageText msg

Output

[ReAct Iteration 1]
Thought: I should read the contents of /tmp/server_status.txt to check the current health status.
Action: read_file {"path": "/tmp/server_status.txt"}
Observation: Service: api-gateway, Status: Degraded, Latency: 420ms

[ReAct Iteration 2]
Thought: The file has been read. The api-gateway service is in a degraded state with elevated latency. I will now summarize this for the user.

Final Answer:
The api-gateway service is currently experiencing degraded health with high latency (420ms). Immediate investigation of the gateway service is recommended.

Documentation & Resources


Development & Testing

# Build project
stack build

# Run test suite
stack test

# Code quality checks
make lint
make format-check

License

Distributed under the MIT License. See LICENSE for details.