diff --git a/dist/restore-only/index.js b/dist/restore-only/index.js
index 2be8885..b646cbf 100644
--- a/dist/restore-only/index.js
+++ b/dist/restore-only/index.js
@@ -4950,12 +4950,13 @@ var Inputs;
     Inputs["Path"] = "path";
     Inputs["RestoreKeys"] = "restore-keys";
     Inputs["UploadChunkSize"] = "upload-chunk-size";
+    Inputs["RestoredKey"] = "restored-key"; // Input from save action
 })(Inputs = exports.Inputs || (exports.Inputs = {}));
 var Outputs;
 (function (Outputs) {
     Outputs["CacheHit"] = "cache-hit";
-    Outputs["Key"] = "key";
-    Outputs["MatchedKey"] = "matched-key";
+    Outputs["InputtedKey"] = "inputted-key";
+    Outputs["MatchedKey"] = "matched-key"; // Output from restore action
 })(Outputs = exports.Outputs || (exports.Outputs = {}));
 var State;
 (function (State) {
@@ -9360,7 +9361,7 @@ const constants_1 = __webpack_require__(196);
 class StateProviderBase {
     constructor() {
         // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
-        this.setState = (key, value) => { };
+        this.setState = (key, value, outputKey) => { };
         // eslint-disable-next-line @typescript-eslint/no-unused-vars
         this.getState = (key) => "";
     }
@@ -9384,7 +9385,11 @@ exports.StateProvider = StateProvider;
 class NullStateProvider extends StateProviderBase {
     constructor() {
         super(...arguments);
-        this.setState = core.setOutput;
+        this.setState = (key, value, outputKey) => {
+            if (outputKey) {
+                core.setOutput(outputKey, value);
+            }
+        };
         // eslint-disable-next-line @typescript-eslint/no-unused-vars
         this.getState = (key) => "";
     }
@@ -50462,7 +50467,7 @@ function restoreImpl(stateProvider) {
                 return;
             }
             const primaryKey = core.getInput(constants_1.Inputs.Key, { required: true });
-            stateProvider.setState(constants_1.State.CachePrimaryKey, primaryKey);
+            stateProvider.setState(constants_1.State.CachePrimaryKey, primaryKey, constants_1.Outputs.InputtedKey);
             const restoreKeys = utils.getInputAsArray(constants_1.Inputs.RestoreKeys);
             const cachePaths = utils.getInputAsArray(constants_1.Inputs.Path, {
                 required: true
@@ -50476,7 +50481,7 @@ function restoreImpl(stateProvider) {
                 return;
             }
             // Store the matched cache key in states
-            stateProvider.setState(constants_1.State.CacheMatchedKey, cacheKey);
+            stateProvider.setState(constants_1.State.CacheMatchedKey, cacheKey, constants_1.Outputs.MatchedKey);
             const isExactKeyMatch = utils.isExactKeyMatch(core.getInput(constants_1.Inputs.Key, { required: true }), cacheKey);
             core.setOutput(constants_1.Outputs.CacheHit, isExactKeyMatch.toString());
             core.info(`Cache restored from key: ${cacheKey}`);
diff --git a/dist/restore/index.js b/dist/restore/index.js
index b300147..18e2e92 100644
--- a/dist/restore/index.js
+++ b/dist/restore/index.js
@@ -4950,12 +4950,13 @@ var Inputs;
     Inputs["Path"] = "path";
     Inputs["RestoreKeys"] = "restore-keys";
     Inputs["UploadChunkSize"] = "upload-chunk-size";
+    Inputs["RestoredKey"] = "restored-key"; // Input from save action
 })(Inputs = exports.Inputs || (exports.Inputs = {}));
 var Outputs;
 (function (Outputs) {
     Outputs["CacheHit"] = "cache-hit";
-    Outputs["Key"] = "key";
-    Outputs["MatchedKey"] = "matched-key";
+    Outputs["InputtedKey"] = "inputted-key";
+    Outputs["MatchedKey"] = "matched-key"; // Output from restore action
 })(Outputs = exports.Outputs || (exports.Outputs = {}));
 var State;
 (function (State) {
@@ -9360,7 +9361,7 @@ const constants_1 = __webpack_require__(196);
 class StateProviderBase {
     constructor() {
         // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
-        this.setState = (key, value) => { };
+        this.setState = (key, value, outputKey) => { };
         // eslint-disable-next-line @typescript-eslint/no-unused-vars
         this.getState = (key) => "";
     }
@@ -9384,7 +9385,11 @@ exports.StateProvider = StateProvider;
 class NullStateProvider extends StateProviderBase {
     constructor() {
         super(...arguments);
-        this.setState = core.setOutput;
+        this.setState = (key, value, outputKey) => {
+            if (outputKey) {
+                core.setOutput(outputKey, value);
+            }
+        };
         // eslint-disable-next-line @typescript-eslint/no-unused-vars
         this.getState = (key) => "";
     }
@@ -50462,7 +50467,7 @@ function restoreImpl(stateProvider) {
                 return;
             }
             const primaryKey = core.getInput(constants_1.Inputs.Key, { required: true });
-            stateProvider.setState(constants_1.State.CachePrimaryKey, primaryKey);
+            stateProvider.setState(constants_1.State.CachePrimaryKey, primaryKey, constants_1.Outputs.InputtedKey);
             const restoreKeys = utils.getInputAsArray(constants_1.Inputs.RestoreKeys);
             const cachePaths = utils.getInputAsArray(constants_1.Inputs.Path, {
                 required: true
@@ -50476,7 +50481,7 @@ function restoreImpl(stateProvider) {
                 return;
             }
             // Store the matched cache key in states
-            stateProvider.setState(constants_1.State.CacheMatchedKey, cacheKey);
+            stateProvider.setState(constants_1.State.CacheMatchedKey, cacheKey, constants_1.Outputs.MatchedKey);
             const isExactKeyMatch = utils.isExactKeyMatch(core.getInput(constants_1.Inputs.Key, { required: true }), cacheKey);
             core.setOutput(constants_1.Outputs.CacheHit, isExactKeyMatch.toString());
             core.info(`Cache restored from key: ${cacheKey}`);
diff --git a/dist/save-only/index.js b/dist/save-only/index.js
index 1e38452..9c29969 100644
--- a/dist/save-only/index.js
+++ b/dist/save-only/index.js
@@ -4979,12 +4979,13 @@ var Inputs;
     Inputs["Path"] = "path";
     Inputs["RestoreKeys"] = "restore-keys";
     Inputs["UploadChunkSize"] = "upload-chunk-size";
+    Inputs["RestoredKey"] = "restored-key"; // Input from save action
 })(Inputs = exports.Inputs || (exports.Inputs = {}));
 var Outputs;
 (function (Outputs) {
     Outputs["CacheHit"] = "cache-hit";
-    Outputs["Key"] = "key";
-    Outputs["MatchedKey"] = "matched-key";
+    Outputs["InputtedKey"] = "inputted-key";
+    Outputs["MatchedKey"] = "matched-key"; // Output from restore action
 })(Outputs = exports.Outputs || (exports.Outputs = {}));
 var State;
 (function (State) {
@@ -9389,7 +9390,7 @@ const constants_1 = __webpack_require__(196);
 class StateProviderBase {
     constructor() {
         // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
-        this.setState = (key, value) => { };
+        this.setState = (key, value, outputKey) => { };
         // eslint-disable-next-line @typescript-eslint/no-unused-vars
         this.getState = (key) => "";
     }
@@ -9413,7 +9414,11 @@ exports.StateProvider = StateProvider;
 class NullStateProvider extends StateProviderBase {
     constructor() {
         super(...arguments);
-        this.setState = core.setOutput;
+        this.setState = (key, value, outputKey) => {
+            if (outputKey) {
+                core.setOutput(outputKey, value);
+            }
+        };
         // eslint-disable-next-line @typescript-eslint/no-unused-vars
         this.getState = (key) => "";
     }
@@ -41075,6 +41080,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
 const cache = __importStar(__webpack_require__(692));
 const core = __importStar(__webpack_require__(470));
 const constants_1 = __webpack_require__(196);
+const stateProvider_1 = __webpack_require__(309);
 const utils = __importStar(__webpack_require__(443));
 // Catch and log any unhandled exceptions.  These exceptions can leak out of the uploadChunk method in
 // @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to
@@ -41095,13 +41101,18 @@ function saveImpl(stateProvider) {
             const primaryKey = stateProvider.getState(constants_1.State.CachePrimaryKey) ||
                 core.getInput(constants_1.Inputs.Key);
             if (!primaryKey) {
-                utils.logWarning(`Error retrieving key from state.`);
+                if (stateProvider instanceof stateProvider_1.StateProvider) {
+                    utils.logWarning(`Error retrieving key from state.`);
+                }
+                else {
+                    utils.logWarning(`Error retrieving key from input.`);
+                }
                 return;
             }
             // If matched restore key is same as primary key, then do not save cache
             // NO-OP in case of SaveOnly action
-            const state = stateProvider.getCacheState();
-            if (utils.isExactKeyMatch(primaryKey, state)) {
+            const restoredKey = stateProvider.getCacheState() || core.getInput(constants_1.Inputs.RestoredKey);
+            if (utils.isExactKeyMatch(primaryKey, restoredKey)) {
                 core.info(`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`);
                 return;
             }
diff --git a/dist/save/index.js b/dist/save/index.js
index 9e3cec7..69ea907 100644
--- a/dist/save/index.js
+++ b/dist/save/index.js
@@ -4950,12 +4950,13 @@ var Inputs;
     Inputs["Path"] = "path";
     Inputs["RestoreKeys"] = "restore-keys";
     Inputs["UploadChunkSize"] = "upload-chunk-size";
+    Inputs["RestoredKey"] = "restored-key"; // Input from save action
 })(Inputs = exports.Inputs || (exports.Inputs = {}));
 var Outputs;
 (function (Outputs) {
     Outputs["CacheHit"] = "cache-hit";
-    Outputs["Key"] = "key";
-    Outputs["MatchedKey"] = "matched-key";
+    Outputs["InputtedKey"] = "inputted-key";
+    Outputs["MatchedKey"] = "matched-key"; // Output from restore action
 })(Outputs = exports.Outputs || (exports.Outputs = {}));
 var State;
 (function (State) {
@@ -9360,7 +9361,7 @@ const constants_1 = __webpack_require__(196);
 class StateProviderBase {
     constructor() {
         // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
-        this.setState = (key, value) => { };
+        this.setState = (key, value, outputKey) => { };
         // eslint-disable-next-line @typescript-eslint/no-unused-vars
         this.getState = (key) => "";
     }
@@ -9384,7 +9385,11 @@ exports.StateProvider = StateProvider;
 class NullStateProvider extends StateProviderBase {
     constructor() {
         super(...arguments);
-        this.setState = core.setOutput;
+        this.setState = (key, value, outputKey) => {
+            if (outputKey) {
+                core.setOutput(outputKey, value);
+            }
+        };
         // eslint-disable-next-line @typescript-eslint/no-unused-vars
         this.getState = (key) => "";
     }
@@ -41046,6 +41051,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
 const cache = __importStar(__webpack_require__(692));
 const core = __importStar(__webpack_require__(470));
 const constants_1 = __webpack_require__(196);
+const stateProvider_1 = __webpack_require__(309);
 const utils = __importStar(__webpack_require__(443));
 // Catch and log any unhandled exceptions.  These exceptions can leak out of the uploadChunk method in
 // @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to
@@ -41066,13 +41072,18 @@ function saveImpl(stateProvider) {
             const primaryKey = stateProvider.getState(constants_1.State.CachePrimaryKey) ||
                 core.getInput(constants_1.Inputs.Key);
             if (!primaryKey) {
-                utils.logWarning(`Error retrieving key from state.`);
+                if (stateProvider instanceof stateProvider_1.StateProvider) {
+                    utils.logWarning(`Error retrieving key from state.`);
+                }
+                else {
+                    utils.logWarning(`Error retrieving key from input.`);
+                }
                 return;
             }
             // If matched restore key is same as primary key, then do not save cache
             // NO-OP in case of SaveOnly action
-            const state = stateProvider.getCacheState();
-            if (utils.isExactKeyMatch(primaryKey, state)) {
+            const restoredKey = stateProvider.getCacheState() || core.getInput(constants_1.Inputs.RestoredKey);
+            if (utils.isExactKeyMatch(primaryKey, restoredKey)) {
                 core.info(`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`);
                 return;
             }
diff --git a/restore/action.yml b/restore/action.yml
index 64079cf..4729458 100644
--- a/restore/action.yml
+++ b/restore/action.yml
@@ -14,7 +14,7 @@ inputs:
 outputs:
   cache-hit:
     description: 'A boolean value to indicate an exact match was found for the primary key'
-  key:
+  inputted-key:
     description: 'Key passed in the input to use in subsequent steps of the workflow'
   matched-key:
     description: 'Cache key restored'
diff --git a/save/action.yml b/save/action.yml
index 71ec649..220de82 100644
--- a/save/action.yml
+++ b/save/action.yml
@@ -11,7 +11,7 @@ inputs:
   upload-chunk-size:
     description: 'The chunk size used to split up large files during upload, in bytes'
     required: false
-  matched-key:
+  restored-key:
     description: 'Cache key restored from the restore action'
     required: false
 runs:
diff --git a/src/constants.ts b/src/constants.ts
index c9c8a81..69d6379 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -1,14 +1,15 @@
 export enum Inputs {
-    Key = "key",
-    Path = "path",
-    RestoreKeys = "restore-keys",
-    UploadChunkSize = "upload-chunk-size"
+    Key = "key", // Input from cache, restore, save action
+    Path = "path", // Input from cache, restore, save action
+    RestoreKeys = "restore-keys", // Input from cache, restore action
+    UploadChunkSize = "upload-chunk-size", // Input from cache, save action
+    RestoredKey = "restored-key" // Input from save action
 }
 
 export enum Outputs {
-    CacheHit = "cache-hit",
-    Key = "key",
-    MatchedKey = "matched-key"
+    CacheHit = "cache-hit", // Output from cache, restore action
+    InputtedKey = "inputted-key", // Output from restore action
+    MatchedKey = "matched-key" // Output from restore action
 }
 
 export enum State {
diff --git a/src/restoreImpl.ts b/src/restoreImpl.ts
index dec2437..3a57f90 100644
--- a/src/restoreImpl.ts
+++ b/src/restoreImpl.ts
@@ -25,7 +25,11 @@ async function restoreImpl(
         }
 
         const primaryKey = core.getInput(Inputs.Key, { required: true });
-        stateProvider.setState(State.CachePrimaryKey, primaryKey);
+        stateProvider.setState(
+            State.CachePrimaryKey,
+            primaryKey,
+            Outputs.InputtedKey
+        );
 
         const restoreKeys = utils.getInputAsArray(Inputs.RestoreKeys);
         const cachePaths = utils.getInputAsArray(Inputs.Path, {
@@ -50,7 +54,11 @@ async function restoreImpl(
         }
 
         // Store the matched cache key in states
-        stateProvider.setState(State.CacheMatchedKey, cacheKey);
+        stateProvider.setState(
+            State.CacheMatchedKey,
+            cacheKey,
+            Outputs.MatchedKey
+        );
 
         const isExactKeyMatch = utils.isExactKeyMatch(
             core.getInput(Inputs.Key, { required: true }),
diff --git a/src/saveImpl.ts b/src/saveImpl.ts
index 1e28e28..67534c7 100644
--- a/src/saveImpl.ts
+++ b/src/saveImpl.ts
@@ -2,7 +2,7 @@ import * as cache from "@actions/cache";
 import * as core from "@actions/core";
 
 import { Events, Inputs, State } from "./constants";
-import { IStateProvider } from "./stateProvider";
+import { IStateProvider, StateProvider } from "./stateProvider";
 import * as utils from "./utils/actionUtils";
 
 // Catch and log any unhandled exceptions.  These exceptions can leak out of the uploadChunk method in
@@ -32,14 +32,20 @@ async function saveImpl(stateProvider: IStateProvider): Promise<void> {
             core.getInput(Inputs.Key);
 
         if (!primaryKey) {
-            utils.logWarning(`Error retrieving key from state.`);
+            if (stateProvider instanceof StateProvider) {
+                utils.logWarning(`Error retrieving key from state.`);
+            } else {
+                utils.logWarning(`Error retrieving key from input.`);
+            }
             return;
         }
 
         // If matched restore key is same as primary key, then do not save cache
         // NO-OP in case of SaveOnly action
-        const state = stateProvider.getCacheState();
-        if (utils.isExactKeyMatch(primaryKey, state)) {
+        const restoredKey =
+            stateProvider.getCacheState() || core.getInput(Inputs.RestoredKey);
+
+        if (utils.isExactKeyMatch(primaryKey, restoredKey)) {
             core.info(
                 `Cache hit occurred on the primary key ${primaryKey}, not saving cache.`
             );
diff --git a/src/stateProvider.ts b/src/stateProvider.ts
index 1d43af4..71cf33b 100644
--- a/src/stateProvider.ts
+++ b/src/stateProvider.ts
@@ -3,7 +3,7 @@ import * as core from "@actions/core";
 import { State } from "./constants";
 
 export interface IStateProvider {
-    setState(key: string, value: string): void;
+    setState(key: string, value: string, outputKey?: string): void;
     getState(key: string): string;
 
     getCacheState(): string | undefined;
@@ -21,7 +21,7 @@ class StateProviderBase implements IStateProvider {
     }
 
     // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
-    setState = (key: string, value: string) => {};
+    setState = (key: string, value: string, outputKey?: string) => {};
 
     // eslint-disable-next-line @typescript-eslint/no-unused-vars
     getState = (key: string) => "";
@@ -33,7 +33,11 @@ export class StateProvider extends StateProviderBase {
 }
 
 export class NullStateProvider extends StateProviderBase {
-    setState = core.setOutput;
+    setState = (key: string, value: string, outputKey?: string) => {
+        if (outputKey) {
+            core.setOutput(outputKey, value);
+        }
+    };
     // eslint-disable-next-line @typescript-eslint/no-unused-vars
     getState = (key: string) => "";
 }