Skip to content

Commit e2e496b

Browse files
committed
Add agent tool domain types: ToolScope, ToolRiskLevel enums, ITaskdeckTool, ITaskdeckToolRegistry interfaces, and PolicyDecision value object
Part of #337 (AGT-02). These domain primitives define the tool abstraction, scope/risk classification, and policy decision contract that the Application layer policy evaluator and tool registry build on.
1 parent 440a8c9 commit e2e496b

5 files changed

Lines changed: 131 additions & 0 deletions

File tree

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using Taskdeck.Domain.Enums;
2+
3+
namespace Taskdeck.Domain.Agents;
4+
5+
/// <summary>
6+
/// Describes a tool that an agent can invoke. Tools are registered in the
7+
/// tool registry and evaluated by the policy engine before execution.
8+
/// </summary>
9+
public interface ITaskdeckTool
10+
{
11+
/// <summary>Unique machine-readable key (e.g. "inbox.triage", "board.create-card").</summary>
12+
string Key { get; }
13+
14+
/// <summary>Human-readable display name shown in review UIs.</summary>
15+
string DisplayName { get; }
16+
17+
/// <summary>Short description of what this tool does.</summary>
18+
string Description { get; }
19+
20+
/// <summary>The operational scope this tool acts within.</summary>
21+
ToolScope Scope { get; }
22+
23+
/// <summary>Risk classification used by the policy evaluator.</summary>
24+
ToolRiskLevel RiskLevel { get; }
25+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using Taskdeck.Domain.Enums;
2+
3+
namespace Taskdeck.Domain.Agents;
4+
5+
/// <summary>
6+
/// Registry of all available agent tools. Populated at application startup
7+
/// and queried by the policy evaluator and agent templates.
8+
/// </summary>
9+
public interface ITaskdeckToolRegistry
10+
{
11+
/// <summary>Register a tool. Throws if a tool with the same key is already registered.</summary>
12+
void RegisterTool(ITaskdeckTool tool);
13+
14+
/// <summary>Look up a tool by its unique key. Returns null if not found.</summary>
15+
ITaskdeckTool? GetTool(string key);
16+
17+
/// <summary>Return all registered tools.</summary>
18+
IReadOnlyList<ITaskdeckTool> GetAllTools();
19+
20+
/// <summary>Return tools filtered by operational scope.</summary>
21+
IReadOnlyList<ITaskdeckTool> GetToolsByScope(ToolScope scope);
22+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
namespace Taskdeck.Domain.Agents;
2+
3+
/// <summary>
4+
/// Value object representing the outcome of a policy evaluation for a tool use request.
5+
/// Immutable by design — once produced by the policy evaluator, a decision is final.
6+
/// </summary>
7+
public sealed class PolicyDecision
8+
{
9+
/// <summary>Whether the tool invocation is allowed to proceed.</summary>
10+
public bool Allowed { get; }
11+
12+
/// <summary>Whether the result must be routed through the review gate before applying.</summary>
13+
public bool RequiresReview { get; }
14+
15+
/// <summary>Human-readable reason for the decision, suitable for audit trails.</summary>
16+
public string Reason { get; }
17+
18+
private PolicyDecision(bool allowed, bool requiresReview, string reason)
19+
{
20+
Allowed = allowed;
21+
RequiresReview = requiresReview;
22+
Reason = reason;
23+
}
24+
25+
/// <summary>Create a decision allowing execution but requiring proposal review.</summary>
26+
public static PolicyDecision AllowWithReview(string reason)
27+
=> new(true, true, reason);
28+
29+
/// <summary>Create a decision denying execution entirely.</summary>
30+
public static PolicyDecision Deny(string reason)
31+
=> new(false, false, reason);
32+
33+
/// <summary>Create a decision allowing direct execution (low-risk, auto-apply enabled).</summary>
34+
public static PolicyDecision AllowDirect(string reason)
35+
=> new(true, false, reason);
36+
37+
public override bool Equals(object? obj)
38+
{
39+
if (obj is not PolicyDecision other) return false;
40+
return Allowed == other.Allowed
41+
&& RequiresReview == other.RequiresReview
42+
&& Reason == other.Reason;
43+
}
44+
45+
public override int GetHashCode()
46+
=> HashCode.Combine(Allowed, RequiresReview, Reason);
47+
48+
public override string ToString()
49+
=> $"PolicyDecision(Allowed={Allowed}, RequiresReview={RequiresReview}, Reason=\"{Reason}\")";
50+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace Taskdeck.Domain.Enums;
2+
3+
/// <summary>
4+
/// Risk classification for agent tools. Determines policy evaluation behavior.
5+
/// High and Medium risk tools require review by default; Low risk tools
6+
/// are still review-first unless explicitly configured otherwise.
7+
/// </summary>
8+
public enum ToolRiskLevel
9+
{
10+
/// <summary>Read-only or informational tools with no mutation side effects.</summary>
11+
Low = 0,
12+
13+
/// <summary>Tools that create or update entities within a bounded scope.</summary>
14+
Medium = 1,
15+
16+
/// <summary>Tools that delete, archive, or perform cross-scope mutations.</summary>
17+
High = 2
18+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
namespace Taskdeck.Domain.Enums;
2+
3+
/// <summary>
4+
/// Defines the operational scope of an agent tool.
5+
/// </summary>
6+
public enum ToolScope
7+
{
8+
/// <summary>Tool operates on a specific board (columns, cards, labels).</summary>
9+
Board = 0,
10+
11+
/// <summary>Tool operates on the capture inbox (triage, categorization).</summary>
12+
Inbox = 1,
13+
14+
/// <summary>Tool operates at workspace/global level (settings, cross-board).</summary>
15+
Global = 2
16+
}

0 commit comments

Comments
 (0)