Skip to content

Commit 45affe2

Browse files
authored
Update SKILL.md and sync with README.md (#213)
* use more explicit instantiation * sync readme and skill * reference skill in readme
1 parent 4838409 commit 45affe2

2 files changed

Lines changed: 284 additions & 92 deletions

File tree

README.md

Lines changed: 90 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ A comprehensive .NET client library for [Conductor](https://github.com/conductor
55
[![NuGet](https://img.shields.io/nuget/v/ConductorSharp.Client.svg)](https://www.nuget.org/packages/ConductorSharp.Client)
66
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
77

8-
98
**Note: This documentation has been AI generated and human reviewed.**
109

10+
> **AI Assistant Users**: See [SKILL.md](SKILL.md) for a condensed reference guide optimized for AI coding assistants. It provides quick-reference documentation for all task types, configuration options, and common patterns. This file follows the [Agent Skills](https://code.claude.com/docs/en/skills) open standard for extending AI assistant capabilities.
11+
1112
## Table of Contents
1213

1314
- [Installation](#installation)
@@ -26,6 +27,7 @@ A comprehensive .NET client library for [Conductor](https://github.com/conductor
2627
- [Toolkit CLI](#toolkit-cli)
2728
- [API Services](#api-services)
2829
- [Running the Examples](#running-the-examples)
30+
- [General Notes](#general-notes)
2931

3032
## Installation
3133

@@ -141,19 +143,19 @@ public class SendNotificationWorkflow : Workflow<SendNotificationWorkflow, SendN
141143
{
142144
_builder.AddTask(
143145
wf => wf.GetCustomer,
144-
wf => new() { CustomerId = wf.WorkflowInput.CustomerId }
146+
wf => new GetCustomerRequest { CustomerId = wf.WorkflowInput.CustomerId }
145147
);
146148

147149
_builder.AddTask(
148150
wf => wf.PrepareEmail,
149-
wf => new()
151+
wf => new PrepareEmailRequest
150152
{
151153
CustomerName = wf.GetCustomer.Output.Name,
152154
Address = wf.GetCustomer.Output.Address
153155
}
154156
);
155157

156-
_builder.SetOutput(wf => new()
158+
_builder.SetOutput(wf => new SendNotificationOutput
157159
{
158160
EmailBody = wf.PrepareEmail.Output.EmailBody
159161
});
@@ -180,11 +182,11 @@ public class MyWorkflow : Workflow<MyWorkflow, MyWorkflowInput, MyWorkflowOutput
180182
public override void BuildDefinition()
181183
{
182184
// Add tasks with strongly-typed input expressions
183-
_builder.AddTask(wf => wf.FirstTask, wf => new() { Input = wf.WorkflowInput.SomeValue });
184-
_builder.AddTask(wf => wf.SecondTask, wf => new() { Input = wf.FirstTask.Output.Result });
185+
_builder.AddTask(wf => wf.FirstTask, wf => new SomeTaskRequest { Input = wf.WorkflowInput.SomeValue });
186+
_builder.AddTask(wf => wf.SecondTask, wf => new AnotherTaskRequest { Input = wf.FirstTask.Output.Result });
185187

186188
// Set workflow output
187-
_builder.SetOutput(wf => new() { Result = wf.SecondTask.Output.Value });
189+
_builder.SetOutput(wf => new MyWorkflowOutput { Result = wf.SecondTask.Output.Value });
188190
}
189191
}
190192
```
@@ -449,20 +451,30 @@ Note: `StringAddition` has an attribute `[OriginalName("string_addition")]` appl
449451
| `[Version(n)]` | Class | Version number for sub-workflow references |
450452
| `[TaskDomain("domain")]` | Class | Assign task to specific domain |
451453

454+
Note: There is no task equivalent of the `WorkflowMetadata` attribute. The task metadata is configured when registering the task:
455+
456+
```csharp
457+
services.RegisterWorkerTask<MyTaskHandler>(options =>
458+
{
459+
options.OwnerEmail = "team@example.com";
460+
options.Description = "My task description";
461+
});
462+
```
463+
452464
## Task Types
453465

454466
### Simple Task
455467

456468
```csharp
457-
_builder.AddTask(wf => wf.MySimpleTask, wf => new() { Input = wf.WorkflowInput.Value });
469+
_builder.AddTask(wf => wf.MySimpleTask, wf => new MySimpleTaskRequest { Input = wf.WorkflowInput.Value });
458470
```
459471

460472
### Sub-Workflow Task
461473

462474
```csharp
463475
public SubWorkflowTaskModel<ChildWorkflowInput, ChildWorkflowOutput> ChildWorkflow { get; set; }
464476

465-
_builder.AddTask(wf => wf.ChildWorkflow, wf => new() { CustomerId = wf.WorkflowInput.CustomerId });
477+
_builder.AddTask(wf => wf.ChildWorkflow, wf => new ChildWorkflowInput { CustomerId = wf.WorkflowInput.CustomerId });
466478
```
467479

468480
### Switch Task (Conditional Branching)
@@ -477,8 +489,8 @@ _builder.AddTask(
477489
wf => new SwitchTaskInput { SwitchCaseValue = wf.WorkflowInput.Operation },
478490
new DecisionCases<MyWorkflow>
479491
{
480-
["caseA"] = builder => builder.AddTask(wf => wf.TaskInCaseA, wf => new() { }),
481-
["caseB"] = builder => builder.AddTask(wf => wf.TaskInCaseB, wf => new() { }),
492+
["caseA"] = builder => builder.AddTask(wf => wf.TaskInCaseA, wf => new TaskARequest { }),
493+
["caseB"] = builder => builder.AddTask(wf => wf.TaskInCaseB, wf => new TaskBRequest { }),
482494
DefaultCase = builder => { /* default case tasks */ }
483495
}
484496
);
@@ -491,9 +503,9 @@ public DynamicTaskModel<ExpectedInput, ExpectedOutput> DynamicHandler { get; set
491503

492504
_builder.AddTask(
493505
wf => wf.DynamicHandler,
494-
wf => new()
506+
wf => new DynamicTaskInput<ExpectedInput, ExpectedOutput>
495507
{
496-
TaskInput = new() { CustomerId = wf.WorkflowInput.CustomerId },
508+
TaskInput = new ExpectedInput { CustomerId = wf.WorkflowInput.CustomerId },
497509
TaskToExecute = wf.WorkflowInput.TaskName // Task name resolved at runtime
498510
}
499511
);
@@ -514,18 +526,70 @@ _builder.AddTask(
514526
);
515527
```
516528

529+
### Do-While Loop Task
530+
531+
```csharp
532+
public DoWhileTaskModel DoWhile { get; set; }
533+
public CustomerGetHandler GetCustomer { get; set; }
534+
535+
_builder.AddTask(
536+
wf => wf.DoWhile,
537+
wf => new DoWhileInput { Value = wf.WorkflowInput.Loops },
538+
"$.do_while.iteration < $.value", // Loop condition
539+
builder =>
540+
{
541+
builder.AddTask(wf => wf.GetCustomer, wf => new CustomerGetRequest { CustomerId = "CUSTOMER-1" });
542+
}
543+
);
544+
```
545+
546+
Note: ConductorSharp does not provide a strongly typed output for the `DoWhile` task, as can be seen from the implementation:
547+
548+
```csharp
549+
public class DoWhileTaskModel : TaskModel<DoWhileInput, NoOutput>
550+
{
551+
}
552+
```
553+
517554
### Lambda Task (JavaScript)
518555

519556
```csharp
557+
public class LambdaInput : IRequest<LambdaOutput>
558+
{
559+
public string Value { get; set; }
560+
}
561+
562+
public class LambdaOutput
563+
{
564+
public string Something { get; set; }
565+
}
566+
520567
public LambdaTaskModel<LambdaInput, LambdaOutput> LambdaTask { get; set; }
521568

569+
522570
_builder.AddTask(
523571
wf => wf.LambdaTask,
524-
wf => new() { Value = wf.WorkflowInput.Input },
525-
script: "return { result: $.Value.toUpperCase() }"
572+
wf => new LambdaInput { Value = wf.WorkflowInput.Input },
573+
script: "return { something: $.Value.toUpperCase() }" // JavaScript expression
526574
);
527575
```
528576

577+
For context, in the above parameterized generic class `LambdaTaskModel`, the `LambdaOutput` instance is available as `Output.Result.Something`. This is less than ideal, but is the current way of things. Reasoning can be seen in the implementation:
578+
579+
```csharp
580+
public abstract class LambdaOutputModel<O>
581+
{
582+
public O Result { get; set; }
583+
}
584+
585+
public abstract class LambdaTaskModel<I, O> where I : IRequest<O>
586+
{
587+
public I Input { get; set; }
588+
589+
public LambdaOutputModel<O> Output { get; set; }
590+
}
591+
```
592+
529593
### Wait Task
530594

531595
```csharp
@@ -552,18 +616,6 @@ _builder.AddTask(
552616
);
553617
```
554618

555-
### Event Task
556-
557-
```csharp
558-
public EventTaskModel<EventInput> EventTask { get; set; }
559-
560-
_builder.AddTask(
561-
wf => wf.EventTask,
562-
wf => new() { EventData = wf.WorkflowInput.Data },
563-
sink: "kafka:my-topic"
564-
);
565-
```
566-
567619
### Human Task
568620

569621
```csharp
@@ -582,7 +634,7 @@ public JsonJqTransformTaskModel<JqInput, JqOutput> TransformTask { get; set; }
582634

583635
_builder.AddTask(
584636
wf => wf.TransformTask,
585-
wf => new() { QueryExpression = ".data | map(.name)", Data = wf.WorkflowInput.Items }
637+
wf => new JqInput { QueryExpression = ".data | map(.name)", Data = wf.WorkflowInput.Items }
586638
);
587639
```
588640

@@ -605,7 +657,7 @@ _builder.AddTasks(new WorkflowTask
605657
Mark tasks as optional (workflow continues on failure):
606658

607659
```csharp
608-
_builder.AddTask(wf => wf.OptionalTask, wf => new() { }).AsOptional();
660+
_builder.AddTask(wf => wf.OptionalTask, wf => new OptionalTaskRequest { }).AsOptional();
609661
```
610662

611663
## Configuration
@@ -762,7 +814,7 @@ Additional built-in tasks and utilities:
762814
```csharp
763815
public WaitSeconds WaitTask { get; set; }
764816

765-
_builder.AddTask(wf => wf.WaitTask, wf => new() { Seconds = 30 });
817+
_builder.AddTask(wf => wf.WaitTask, wf => new WaitSecondsRequest { Seconds = 30 });
766818
```
767819

768820
### ReadWorkflowTasks Task
@@ -774,7 +826,7 @@ public ReadWorkflowTasks ReadTasks { get; set; }
774826

775827
_builder.AddTask(
776828
wf => wf.ReadTasks,
777-
wf => new()
829+
wf => new ReadWorkflowTasksInput
778830
{
779831
WorkflowId = wf.WorkflowInput.TargetWorkflowId,
780832
TaskNames = "task1,task2" // Comma-separated reference names
@@ -791,7 +843,7 @@ public CSharpLambdaTaskModel<LambdaInput, LambdaOutput> InlineLambda { get; set;
791843

792844
_builder.AddTask(
793845
wf => wf.InlineLambda,
794-
wf => new() { Value = wf.WorkflowInput.Input },
846+
wf => new LambdaInput { Value = wf.WorkflowInput.Input },
795847
input => new LambdaOutput { Result = input.Value.ToUpperInvariant() }
796848
);
797849
```
@@ -967,6 +1019,12 @@ cd examples/ConductorSharp.Definitions
9671019
dotnet run
9681020
```
9691021

1022+
## General Notes
1023+
1024+
### Events Not Supported
1025+
1026+
The Conductor events are currently not supported by the library.
1027+
9701028
## License
9711029

9721030
MIT License - see [LICENSE](LICENSE) for details.

0 commit comments

Comments
 (0)