diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,13 @@
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## [0.8.7] - 2022-03-09
+
+### Added
+
+ - Nix 2.7 support
+ - Haskell `aeson` 2.0 support
+
 ## [0.8.6] - 2022-03-07
 
 ### Fixed
@@ -488,6 +495,7 @@
 
 - Initial release
 
+[0.8.7]: https://github.com/hercules-ci/hercules-ci-agent/compare/hercules-ci-agent-0.8.6...hercules-ci-agent-0.8.7
 [0.8.6]: https://github.com/hercules-ci/hercules-ci-agent/compare/hercules-ci-agent-0.8.5...hercules-ci-agent-0.8.6
 [0.8.5]: https://github.com/hercules-ci/hercules-ci-agent/compare/hercules-ci-agent-0.8.4...hercules-ci-agent-0.8.5
 [0.8.4]: https://github.com/hercules-ci/hercules-ci-agent/compare/hercules-ci-agent-0.8.3...hercules-ci-agent-0.8.4
diff --git a/cbits/nix-2.4/hercules-store.cxx b/cbits/nix-2.4/hercules-store.cxx
--- a/cbits/nix-2.4/hercules-store.cxx
+++ b/cbits/nix-2.4/hercules-store.cxx
@@ -10,6 +10,10 @@
 #include <nix/derivations.hh>
 #include <nix/globals.hh>
 #include <nix/callback.hh>
+#if NIX_IS_AT_LEAST(2,7,0)
+#include <nix/build-result.hh>
+#include <nix/gc-store.hh>
+#endif
 
 #include "hercules-store.hh"
 
@@ -79,7 +83,13 @@
   wrappedStore->addToStore(info, narSource, repair, checkSigs);
 }
 
-StorePath WrappingStore::addToStore(const string & name, const Path & srcPath,
+StorePath WrappingStore::addToStore(
+#if NIX_IS_AT_LEAST(2,7,0)
+      std::string_view name,
+#else
+      const std::string & name,
+#endif
+      const Path & srcPath,
       FileIngestionMethod method, HashType hashAlgo,
       PathFilter & filter, RepairFlag repair
 #if NIX_IS_AT_LEAST(2,5,0)
@@ -95,8 +105,16 @@
 
 }
 
-StorePath WrappingStore::addToStoreFromDump(Source & dump, const string & name,
-      FileIngestionMethod method, HashType hashAlgo, RepairFlag repair
+StorePath WrappingStore::addToStoreFromDump(
+      Source & dump,
+#if NIX_IS_AT_LEAST(2,7,0)
+      std::string_view name,
+#else
+      const std::string & name,
+#endif
+      FileIngestionMethod method,
+      HashType hashAlgo,
+      RepairFlag repair
 #if NIX_IS_AT_LEAST(2,5,0)
       , const StorePathSet & references
 #endif
@@ -109,7 +127,12 @@
   );
 }
 
-StorePath WrappingStore::addTextToStore(const string & name, const string & s,
+StorePath WrappingStore::addTextToStore(
+#if NIX_IS_AT_LEAST(2,7,0)
+      std::string_view name, std::string_view s,
+#else
+      const std::string & name, const std::string & s,
+#endif
       const StorePathSet & references, RepairFlag repair) {
   return wrappedStore->addTextToStore(name, s, references, repair);
 }
@@ -138,25 +161,31 @@
   wrappedStore->addTempRoot(path);
 }
 
-void WrappingStore::addIndirectRoot(const Path& path) {
-  wrappedStore->addIndirectRoot(path);
-}
-
 #if !NIX_IS_AT_LEAST(2,5,0)
 void WrappingStore::syncWithGC() {
   wrappedStore->syncWithGC();
 }
 #endif
 
+void WrappingStore::optimiseStore() {
+  wrappedStore->optimiseStore();
+};
+
+#if !NIX_IS_AT_LEAST(2,7,0)
 void WrappingStore::collectGarbage(const GCOptions& options,
                                    GCResults& results) {
   wrappedStore->collectGarbage(options, results);
 }
 
-void WrappingStore::optimiseStore() {
-  wrappedStore->optimiseStore();
-};
+void WrappingStore::addIndirectRoot(const Path& path) {
+  wrappedStore->addIndirectRoot(path);
+}
 
+Roots WrappingStore::findRoots(bool censor) {
+  return wrappedStore->findRoots(censor);
+}
+#endif
+
 bool WrappingStore::verifyStore(bool checkContents, RepairFlag repair) {
   return wrappedStore->verifyStore(checkContents, repair);
 };
@@ -202,10 +231,6 @@
 Path WrappingStore::toRealPath(const Path& storePath) {
   return wrappedStore->toRealPath(storePath);
 };
-
-Roots WrappingStore::findRoots(bool censor) {
-  return wrappedStore->findRoots(censor);
-}
 
 unsigned int WrappingStore::getProtocol() {
   return wrappedStore->getProtocol();
diff --git a/cbits/nix-2.4/hercules-store.hh b/cbits/nix-2.4/hercules-store.hh
--- a/cbits/nix-2.4/hercules-store.hh
+++ b/cbits/nix-2.4/hercules-store.hh
@@ -57,7 +57,13 @@
   virtual void addToStore(const ValidPathInfo & info, Source & narSource,
       RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs) override;
 
-  virtual StorePath addToStore(const string & name, const Path & srcPath,
+  virtual StorePath addToStore(
+#if NIX_IS_AT_LEAST(2,7,0)
+      std::string_view name,
+#else
+      const std::string & name,
+#endif
+      const Path & srcPath,
       FileIngestionMethod method = FileIngestionMethod::Recursive, HashType hashAlgo = htSHA256,
       PathFilter & filter = defaultPathFilter, RepairFlag repair = NoRepair
 #if NIX_IS_AT_LEAST(2,5,0)
@@ -65,15 +71,28 @@
 #endif
       ) override;
 
-  virtual StorePath addToStoreFromDump(Source & dump, const string & name,
-      FileIngestionMethod method = FileIngestionMethod::Recursive, HashType hashAlgo = htSHA256, RepairFlag repair = NoRepair
+  virtual StorePath addToStoreFromDump(
+      Source & dump, 
+#if NIX_IS_AT_LEAST(2,7,0)
+      std::string_view name,
+#else
+      const std::string & name,
+#endif
+      FileIngestionMethod method = FileIngestionMethod::Recursive,
+      HashType hashAlgo = htSHA256,
+      RepairFlag repair = NoRepair
 #if NIX_IS_AT_LEAST(2,5,0)
       , const StorePathSet & references = StorePathSet()
 #endif
       ) override;
 
-  virtual StorePath addTextToStore(const string & name, const string & s,
-      const StorePathSet & references, RepairFlag repair = NoRepair) override;
+  virtual StorePath addTextToStore(
+#if NIX_IS_AT_LEAST(2,7,0)
+    std::string_view name, std::string_view s,
+#else
+    const std::string & name, const std::string & s,
+#endif
+    const StorePathSet & references, RepairFlag repair = NoRepair) override;
 
   virtual void narFromPath(const StorePath & path, Sink & sink) override;
 
@@ -89,15 +108,17 @@
 
   virtual void addTempRoot(const StorePath & path) override;
 
-  virtual void addIndirectRoot(const Path & path) override;
-
 #if !NIX_IS_AT_LEAST(2,5,0)
   virtual void syncWithGC() override;
 #endif
 
+#if !NIX_IS_AT_LEAST(2,7,0)
   virtual Roots findRoots(bool censor) override;
 
   virtual void collectGarbage(const GCOptions & options, GCResults & results) override;
+
+  virtual void addIndirectRoot(const Path & path) override;
+#endif
 
   virtual void optimiseStore() override;
 
diff --git a/hercules-ci-agent-worker/Hercules/Agent/Worker.hs b/hercules-ci-agent-worker/Hercules/Agent/Worker.hs
--- a/hercules-ci-agent-worker/Hercules/Agent/Worker.hs
+++ b/hercules-ci-agent-worker/Hercules/Agent/Worker.hs
@@ -509,17 +509,17 @@
     handleErrors path = Data.Conduit.handleC (yieldAttributeError path)
     walk' ::
       (MonadUnliftIO m, KatipContext m) =>
-      -- | If True, always walk this attribute set. Only True for the root.
+      -- If True, always walk this attribute set. Only True for the root.
       Bool ->
-      -- | Attribute path
+      -- Attribute path
       [ByteString] ->
-      -- | Depth of tree remaining
+      -- Depth of tree remaining
       Integer ->
-      -- | Auto arguments to pass to (attrset-)functions
+      -- Auto arguments to pass to (attrset-)functions
       Value NixAttrs ->
-      -- | Current node of the walk
+      -- Current node of the walk
       RawValue ->
-      -- | Program that performs the walk and emits 'Event's
+      -- Program that performs the walk and emits 'Event's
       ConduitT i1 Event m ()
     walk' forceWalkAttrset path depthRemaining autoArgs v =
       -- logLocM DebugS $ logStr $ "Walking " <> (show path :: Text)
diff --git a/hercules-ci-agent-worker/Hercules/Agent/Worker/Build/Prefetched.hs b/hercules-ci-agent-worker/Hercules/Agent/Worker/Build/Prefetched.hs
--- a/hercules-ci-agent-worker/Hercules/Agent/Worker/Build/Prefetched.hs
+++ b/hercules-ci-agent-worker/Hercules/Agent/Worker/Build/Prefetched.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE QuasiQuotes #-}
 {-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE CPP #-}
 
 -- This implements an optimized routine to build from a remote derivation.
 -- It is not in the "CNix" tree because it seems to be too specific for general use.
@@ -35,6 +36,10 @@
 C.include "<nix/globals.hh>"
 
 C.include "<nix/fs-accessor.hh>"
+
+#if NIX_IS_AT_LEAST(2,7,0)
+C.include "<nix/build-result.hh>"
+#endif
 
 C.include "<nix-compat.hh>"
 
diff --git a/hercules-ci-agent.cabal b/hercules-ci-agent.cabal
--- a/hercules-ci-agent.cabal
+++ b/hercules-ci-agent.cabal
@@ -1,7 +1,7 @@
 cabal-version: 2.4
 
 name:           hercules-ci-agent
-version:        0.8.6
+version:        0.8.7
 synopsis:       Runs Continuous Integration tasks on your machines
 category:       Nix, CI, Testing, DevOps
 homepage:       https://docs.hercules-ci.com
@@ -205,7 +205,7 @@
     , filepath
     , hercules-ci-agent
     , hercules-ci-api-core == 0.1.3.0
-    , hercules-ci-api-agent == 0.4.1.1
+    , hercules-ci-api-agent == 0.4.1.2
     , hostname
     , http-client
     , http-client-tls
diff --git a/hercules-ci-agent/Hercules/Agent/Bag.hs b/hercules-ci-agent/Hercules/Agent/Bag.hs
--- a/hercules-ci-agent/Hercules/Agent/Bag.hs
+++ b/hercules-ci-agent/Hercules/Agent/Bag.hs
@@ -9,6 +9,7 @@
 where
 
 import Data.Aeson
+import qualified Data.Aeson.KeyMap as AK
 import Data.Aeson.Types
 import Data.Functor.Compose
 import Data.Functor.Partitioner hiding
@@ -37,7 +38,7 @@
 whenKind :: Text -> (Value -> Maybe a) -> Value -> Maybe a
 whenKind expectedKind f v@(Object o) =
   ( do
-      x <- HashMap.lookup "kind" o
+      x <- AK.lookup "kind" o
       guard (x == String expectedKind)
   )
     *> f v
diff --git a/hercules-ci-agent/Hercules/Agent/Compat.hs b/hercules-ci-agent/Hercules/Agent/Compat.hs
--- a/hercules-ci-agent/Hercules/Agent/Compat.hs
+++ b/hercules-ci-agent/Hercules/Agent/Compat.hs
@@ -5,8 +5,8 @@
 
 #if MIN_VERSION_katip(0,8,0)
 katipLevel :: K.Severity -> K.PermitFunc
-katipLevel =
-  K.permitItem
+katipLevel a =
+  K.permitItem a
 #else
 katipLevel x = x
 #endif
diff --git a/hercules-ci-agent/Hercules/Agent/Config.hs b/hercules-ci-agent/Hercules/Agent/Config.hs
--- a/hercules-ci-agent/Hercules/Agent/Config.hs
+++ b/hercules-ci-agent/Hercules/Agent/Config.hs
@@ -15,6 +15,7 @@
 where
 
 import qualified Data.Aeson as A
+import qualified Data.Aeson.KeyMap as AK
 import Data.Scientific (floatingOrInteger, fromFloatDigits)
 import qualified Data.Vector as V
 import GHC.Conc (getNumProcessors)
@@ -95,13 +96,13 @@
   Codec
     { codecRead =
         codecRead (match (embedJsonBiMap key) key)
-          <!> codecRead (A.Object <$> Toml.tableHashMap _KeyText embedJson key),
+          <!> codecRead (A.Object <$> AK.fromHashMapText <$> Toml.tableHashMap _KeyText embedJson key),
       codecWrite = panic "embedJson.write: not implemented" $ \case
         A.String s -> A.String <$> codecWrite (Toml.text key) s
         A.Number sci -> A.Number . fromRational . toRational <$> codecWrite (Toml.double key) (fromRational $ toRational sci)
         A.Bool b -> A.Bool <$> codecWrite (Toml.bool key) b
         A.Array a -> A.Array . V.fromList <$> codecWrite (Toml.arrayOf (embedJsonBiMap key) key) (Protolude.toList a)
-        A.Object o -> A.Object <$> codecWrite (Toml.tableHashMap _KeyText embedJson key) o
+        A.Object o -> A.Object <$> AK.fromHashMapText <$> codecWrite (Toml.tableHashMap _KeyText embedJson key) (AK.toHashMapText o)
         A.Null -> eitherToTomlState (Left ("null is not supported in TOML" :: Text))
     }
 
