diff --git a/AGI.cabal b/AGI.cabal
--- a/AGI.cabal
+++ b/AGI.cabal
@@ -7,7 +7,7 @@
      can be used to write external programs that interact with
      Asterisk. It is typically used for creating Interactive Voice
      Response (IVR) systems. 
-Version:        1.1.1
+Version:        1.2
 License:        BSD3
 License-File:   LICENSE
 Author:         Jeremy Shaw
@@ -33,9 +33,9 @@
     build-depends:  parsec, mtl
 
     if flag(small_base)
-        build-depends:  base >= 3, random, unix
+        build-depends:  base >= 3, random, unix, network
     else
-        build-depends:  base <  3
+        build-depends:  base <  3, network
 
     Exposed-modules:
             Network.AGI 
diff --git a/Network/AGI.hs b/Network/AGI.hs
--- a/Network/AGI.hs
+++ b/Network/AGI.hs
@@ -3,6 +3,8 @@
     ( Digit(..)
     , AGI
     , run
+    , fastAGI
+    , runInternal
     , ppDigit
     , ppEscapeDigits
     , SoundType(..)
@@ -18,6 +20,8 @@
     , record
     ) where
 
+import Control.Concurrent
+import Control.Exception (finally)
 import Control.Monad
 import Control.Monad.Trans
 import Control.Monad.Reader
@@ -25,14 +29,20 @@
 import Data.Char
 import Data.Maybe
 import Data.Word
+import Network
 import Text.ParserCombinators.Parsec
 import System.IO
 import System.Posix.Signals
 import System.Random
 
-newtype AGI a = AGI { runAGI :: ReaderT [(String, String)] IO a }
-    deriving (Monad, MonadIO, Functor, MonadError IOError, MonadReader [(String, String)])
+data AGIEnv = AGIEnv { agiVars :: [(String, String)]
+                     , agiInH :: Handle
+                     , agiOutH :: Handle
+                     }
 
+newtype AGI a = AGI { runAGI :: ReaderT AGIEnv IO a }
+    deriving (Monad, MonadIO, Functor, MonadError IOError, MonadReader AGIEnv)
+
 data Digit
     = Pound
     | Star
@@ -76,26 +86,54 @@
     show GSM  = "gsm"
 
 -- TODO: let user install a custom sipHUP handler (sigHUP is sent when the caller hangs ups)
+-- |Top-level wrapper for single-shot AGI scripts.
+-- Example:
+-- @ main = run yourAGI Ignore @
 run :: AGI a -> Handler -> IO a
 run agi hupHandler =
     do installHandler sigHUP hupHandler Nothing
-       hSetBuffering stdin LineBuffering
-       hSetBuffering stdout LineBuffering
-       agiVars <- readAgiVars
-       runReaderT (runAGI agi) agiVars
+       runInternal agi stdin stdout
 
-readAgiVars :: IO [(String, String)]
-readAgiVars = 
+-- |Top-level for long running AGI scripts.
+-- Example:
+-- @ main = fastAGI Nothing yourAGI @
+-- You should be sure to compile with -threaded. Note that 'yourAGI'
+-- may be running simultaneously in multiple threads, so you will need
+-- some concurrency control for shared data.
+-- TODO: support a hang-up handler
+fastAGI :: Maybe PortID -> (HostName -> PortNumber -> AGI a) -> IO ()
+fastAGI portId agi =
+    do installHandler sigPIPE Ignore Nothing 
+       s <- listenOn $ fromMaybe (PortNumber 4573) portId
+       (forever $ (do (h, hostname, portNum) <- accept s
+                      forkIO $ runInternal (agi hostname portNum) h h >> hClose h
+                  )) `finally` (sClose s)
+
+
+-- |runInternal - run an AGI script using the supplied Handles for input and output
+-- You probably want 'run' or 'fastAGI'. This function is exposed so
+-- that 3rd party libraries such as HAppS can easily add support for
+-- FastAGI support.
+-- TODO: support general method of handling extra arguments (query_string vs command-line arguments)
+runInternal :: AGI a -> Handle -> Handle -> IO a
+runInternal agi inh outh =
+    do vars <- readAgiVars inh
+       hSetBuffering inh  LineBuffering
+       hSetBuffering outh LineBuffering
+       runReaderT (runAGI agi) (AGIEnv vars inh outh)
+
+readAgiVars :: Handle -> IO [(String, String)]
+readAgiVars inh = 
     do mAgiVar <- readAgiVar 
        case mAgiVar of
 	    Nothing -> 
 		return []
 	    Just agiVar ->
-		do rest <- readAgiVars
+		do rest <- readAgiVars inh
 		   return (agiVar:rest)
     where readAgiVar :: IO (Maybe (String, String))
 	  readAgiVar =
-	      do l <- getLine
+	      do l <- hGetLine inh
 		 case l of
 		      "" -> return Nothing
 		      _ -> let (a,v) = break ((==) ':') l in
@@ -103,8 +141,10 @@
 
 sendRecv :: Command -> AGI String
 sendRecv cmd =
-    liftIO $ do putStrLn cmd
-                getLine
+    do inh  <- liftM agiInH  $ ask
+       outh <- liftM agiOutH $ ask
+       liftIO $ do hPutStrLn inh cmd
+                   hGetLine outh
 
 {-
 Usage: ANSWER
diff --git a/debian/changelog b/debian/changelog
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+haskell-agi (1.2) unstable; urgency=low
+
+  * Added initial support for FastAGI (very lightly tested)
+
+ -- Jeremy Shaw <jeremy@n-heptane.com>  Wed, 02 Jul 2008 23:56:03 -0700
+
 haskell-agi (1.1.1) unstable; urgency=low
 
   * Debianization generated by cabal-debian
