diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/CachedTool.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/CachedTool.kt
new file mode 100644
index 000000000..583bf0aa6
--- /dev/null
+++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/CachedTool.kt
@@ -0,0 +1,33 @@
+package com.xebia.functional.xef.llm.assistants
+
+import arrow.fx.coroutines.Atomic
+import arrow.fx.coroutines.timeInMillis
+import kotlin.time.Duration
+import kotlin.time.Duration.Companion.days
+
+abstract class CachedTool(
+ private val cache: Atomic>>,
+ private val timeCachePolicy: Duration = 1.days
+) : Tool {
+
+ override suspend fun invoke(input: Input): Output {
+ return cache(input) { onCacheMissed(input) }
+ }
+
+ abstract suspend fun onCacheMissed(input: Input): Output
+
+ private suspend fun cache(input: Input, block: suspend () -> Output): Output {
+ val cachedToolInfo = cache.get().get(input)
+ if (cachedToolInfo != null) {
+ val lastTimeInCache = timeInMillis() - timeCachePolicy.inWholeMilliseconds
+ if (lastTimeInCache > cachedToolInfo.timestamp) {
+ cache.get().remove(input)
+ } else {
+ return cachedToolInfo.response
+ }
+ }
+ val response = block()
+ cache.get().put(input, CachedToolInfo(response, timeInMillis()))
+ return response
+ }
+}
diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/CachedToolInfo.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/CachedToolInfo.kt
new file mode 100644
index 000000000..84dd49763
--- /dev/null
+++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/CachedToolInfo.kt
@@ -0,0 +1,3 @@
+package com.xebia.functional.xef.llm.assistants
+
+data class CachedToolInfo(val response: Response, val timestamp: Long)