diff --git a/Automate/Speckle.Automate.Sdk/DataAnnotations/SecretAttribute.cs b/Automate/Speckle.Automate.Sdk/DataAnnotations/SecretAttribute.cs
new file mode 100644
index 0000000000..807e002928
--- /dev/null
+++ b/Automate/Speckle.Automate.Sdk/DataAnnotations/SecretAttribute.cs
@@ -0,0 +1,7 @@
+namespace Speckle.Automate.Sdk.DataAnnotations;
+
+///
+/// If specified, the given function input will be redacted in all contexts.
+///
+[AttributeUsage(AttributeTargets.All)]
+public sealed class SecretAttribute : Attribute { }
diff --git a/Automate/Speckle.Automate.Sdk/Runner.cs b/Automate/Speckle.Automate.Sdk/Runner.cs
index d3b0186adc..8a0d0b6496 100644
--- a/Automate/Speckle.Automate.Sdk/Runner.cs
+++ b/Automate/Speckle.Automate.Sdk/Runner.cs
@@ -1,8 +1,10 @@
using System.CommandLine;
using System.Diagnostics.CodeAnalysis;
+using Newtonsoft.Json;
using Newtonsoft.Json.Schema;
using Newtonsoft.Json.Schema.Generation;
using Newtonsoft.Json.Serialization;
+using Speckle.Automate.Sdk.DataAnnotations;
using Speckle.Automate.Sdk.Schema;
using Speckle.Core.Logging;
@@ -131,6 +133,7 @@ public static async Task Main(string[] args, Func
{
JSchemaGenerator generator = new() { ContractResolver = new CamelCasePropertyNamesContractResolver() };
+ generator.GenerationProviders.Add(new SpeckleSecretProvider());
JSchema schema = generator.Generate(typeof(TInput));
schema.ToString(global::Newtonsoft.Json.Schema.SchemaVersion.Draft2019_09);
File.WriteAllText(schemaFilePath, schema.ToString());
@@ -144,3 +147,34 @@ public static async Task Main(string[] args, Func();
+ var isSecretString = attributes.Any(att => att is SecretAttribute);
+
+ if (isSecretString)
+ {
+ return CreateSchemaWithWriteOnly(context.ObjectType, context.Required);
+ }
+
+ return null;
+ }
+#pragma warning restore CS8764 // Nullability of return type doesn't match overridden member (possibly because of nullability attributes).
+
+
+ private JSchema CreateSchemaWithWriteOnly(Type type, Required required)
+ {
+ JSchemaGenerator generator = new();
+ JSchema schema = generator.Generate(type, required != Required.Always);
+
+ schema.WriteOnly = true;
+
+ return schema;
+ }
+}