langchain-hs-0.0.5.0: src/Langchain/Tool/Async.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{- |
Module : Langchain.Tool.Async
Description : Asynchronous tool execution with timeout, cancellation, and concurrency control
Copyright : (c) 2026 Tushar Adhatrao
License : MIT
Maintainer : Tushar Adhatrao <tusharadhatrao@gmail.com>
Stability : experimental
Provides non-blocking, async tool execution primitives with per-tool timeout limits
and batch concurrent execution.
-}
module Langchain.Tool.Async
( executeToolAsync
, executeToolWithTimeout
, executeToolBatchConcurrently
) where
import Control.Concurrent (threadDelay)
import Control.Concurrent.Async (Async, async, mapConcurrently, race)
import Control.Monad.Except (MonadError, throwError)
import Control.Monad.IO.Class (MonadIO, liftIO)
import Data.Aeson (Value)
import Data.Text (Text)
import qualified Data.Text as T
import Langchain.Core.Error (LangchainError, toolError)
import Langchain.Tool.Core (Tool (..))
-- | Spawn tool execution in an asynchronous background thread
executeToolAsync ::
(MonadIO m) =>
Tool IO ->
Value ->
m (Async (Either LangchainError Text))
executeToolAsync Tool {..} args = liftIO $ do
async (toolExecute args)
-- | Execute a tool with a strict timeout limit in microseconds
executeToolWithTimeout ::
(MonadIO m, MonadError LangchainError m) =>
Tool IO ->
Value ->
Int ->
m Text
executeToolWithTimeout Tool {..} args timeoutMicros = do
res <- liftIO $ race (threadDelay timeoutMicros) (toolExecute args)
case res of
Left () ->
throwError $
toolError
("Tool '" <> toolName <> "' timed out after " <> T.pack (show timeoutMicros) <> " microseconds")
(Just toolName)
Nothing
Right (Left err) -> throwError err
Right (Right output) -> pure output
-- | Execute a batch of tool calls concurrently in parallel
executeToolBatchConcurrently ::
(MonadIO m, MonadError LangchainError m) =>
[(Tool IO, Value)] ->
m [Text]
executeToolBatchConcurrently toolCalls = do
results <- liftIO $ mapConcurrently (uncurry toolExecute) toolCalls
case sequence results of
Left err -> throwError err
Right outputs -> pure outputs