Skip to content

Commit bb970bb

Browse files
authored
Merge pull request #34 from LAA-Software-Engineering/issue/2-spec-kinds
feat(spec): resource envelope and MVP kind structs (#2)
2 parents 7c63fc8 + c37fb50 commit bb970bb

6 files changed

Lines changed: 551 additions & 2 deletions

File tree

go.mod

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ module github.com/LAA-Software-Engineering/agentic-control-plane
22

33
go 1.22
44

5-
require github.com/spf13/cobra v1.8.1
5+
require (
6+
github.com/spf13/cobra v1.8.1
7+
gopkg.in/yaml.v3 v3.0.1
8+
)
69

710
require (
811
github.com/inconshreveable/mousetrap v1.1.0 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,7 @@ github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
66
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
77
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
88
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
9+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
910
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
11+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
1012
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

internal/spec/doc.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
// Package spec parses YAML resources, types, defaults, and validation.
1+
// Package spec defines resource envelopes and MVP kind structs (design doc §6–§7).
2+
// Parsing, defaults, and validation live in future packages.
23
package spec

internal/spec/kinds.go

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
package spec
2+
3+
// --- Project (design doc §7.1) ---
4+
5+
type ProjectSpec struct {
6+
Imports []string `yaml:"imports,omitempty" json:"imports,omitempty"`
7+
Defaults *ProjectDefaults `yaml:"defaults,omitempty" json:"defaults,omitempty"`
8+
Providers *ProjectProviders `yaml:"providers,omitempty" json:"providers,omitempty"`
9+
State *ProjectStateConfig `yaml:"state,omitempty" json:"state,omitempty"`
10+
Traces *ProjectTracesConfig `yaml:"traces,omitempty" json:"traces,omitempty"`
11+
}
12+
13+
type ProjectDefaults struct {
14+
Runtime string `yaml:"runtime,omitempty" json:"runtime,omitempty"`
15+
Model string `yaml:"model,omitempty" json:"model,omitempty"`
16+
Policy string `yaml:"policy,omitempty" json:"policy,omitempty"`
17+
}
18+
19+
type ProjectProviders struct {
20+
Models map[string]ModelProviderConfig `yaml:"models,omitempty" json:"models,omitempty"`
21+
Tools *ProjectToolsProviders `yaml:"tools,omitempty" json:"tools,omitempty"`
22+
}
23+
24+
type ModelProviderConfig struct {
25+
Type string `yaml:"type" json:"type"`
26+
APIKeyFrom string `yaml:"apiKeyFrom,omitempty" json:"apiKeyFrom,omitempty"`
27+
}
28+
29+
type ProjectToolsProviders struct {
30+
MCP *MCPProviderConfig `yaml:"mcp,omitempty" json:"mcp,omitempty"`
31+
}
32+
33+
type MCPProviderConfig struct {
34+
Enabled bool `yaml:"enabled,omitempty" json:"enabled,omitempty"`
35+
}
36+
37+
type ProjectStateConfig struct {
38+
Backend string `yaml:"backend,omitempty" json:"backend,omitempty"`
39+
DSN string `yaml:"dsn,omitempty" json:"dsn,omitempty"`
40+
}
41+
42+
type ProjectTracesConfig struct {
43+
Backend string `yaml:"backend,omitempty" json:"backend,omitempty"`
44+
RetentionDays int `yaml:"retentionDays,omitempty" json:"retentionDays,omitempty"`
45+
}
46+
47+
// --- Agent (design doc §7.2, MVP fields) ---
48+
49+
type AgentSpec struct {
50+
Description string `yaml:"description,omitempty" json:"description,omitempty"`
51+
Model string `yaml:"model,omitempty" json:"model,omitempty"`
52+
Instructions string `yaml:"instructions,omitempty" json:"instructions,omitempty"`
53+
Tools []string `yaml:"tools,omitempty" json:"tools,omitempty"`
54+
Policy string `yaml:"policy,omitempty" json:"policy,omitempty"`
55+
Memory *AgentMemory `yaml:"memory,omitempty" json:"memory,omitempty"`
56+
Constraints *AgentConstraints `yaml:"constraints,omitempty" json:"constraints,omitempty"`
57+
Input *AgentIO `yaml:"input,omitempty" json:"input,omitempty"`
58+
Output *AgentIO `yaml:"output,omitempty" json:"output,omitempty"`
59+
}
60+
61+
type AgentMemory struct {
62+
Type string `yaml:"type,omitempty" json:"type,omitempty"`
63+
MaxMessages int `yaml:"maxMessages,omitempty" json:"maxMessages,omitempty"`
64+
}
65+
66+
type AgentConstraints struct {
67+
MaxIterations int `yaml:"maxIterations,omitempty" json:"maxIterations,omitempty"`
68+
TimeoutSeconds int `yaml:"timeoutSeconds,omitempty" json:"timeoutSeconds,omitempty"`
69+
Temperature float64 `yaml:"temperature,omitempty" json:"temperature,omitempty"`
70+
RequireStructuredOutput bool `yaml:"requireStructuredOutput,omitempty" json:"requireStructuredOutput,omitempty"`
71+
}
72+
73+
type AgentIO struct {
74+
Schema string `yaml:"schema,omitempty" json:"schema,omitempty"`
75+
}
76+
77+
// --- Tool (design doc §7.3, MVP types: mcp, http, native) ---
78+
79+
type ToolSpec struct {
80+
Type string `yaml:"type,omitempty" json:"type,omitempty"`
81+
MCP *ToolMCP `yaml:"mcp,omitempty" json:"mcp,omitempty"`
82+
HTTP *ToolHTTP `yaml:"http,omitempty" json:"http,omitempty"`
83+
Permissions *ToolPermissions `yaml:"permissions,omitempty" json:"permissions,omitempty"`
84+
Retry *ToolRetry `yaml:"retry,omitempty" json:"retry,omitempty"`
85+
}
86+
87+
type ToolMCP struct {
88+
Transport string `yaml:"transport,omitempty" json:"transport,omitempty"`
89+
Command string `yaml:"command,omitempty" json:"command,omitempty"`
90+
Args []string `yaml:"args,omitempty" json:"args,omitempty"`
91+
}
92+
93+
type ToolHTTP struct {
94+
BaseURL string `yaml:"baseUrl,omitempty" json:"baseUrl,omitempty"`
95+
Headers map[string]string `yaml:"headers,omitempty" json:"headers,omitempty"`
96+
}
97+
98+
type ToolPermissions struct {
99+
Allow []string `yaml:"allow,omitempty" json:"allow,omitempty"`
100+
Deny []string `yaml:"deny,omitempty" json:"deny,omitempty"`
101+
}
102+
103+
type ToolRetry struct {
104+
MaxAttempts int `yaml:"maxAttempts,omitempty" json:"maxAttempts,omitempty"`
105+
Backoff string `yaml:"backoff,omitempty" json:"backoff,omitempty"`
106+
}
107+
108+
// --- Workflow (design doc §7.4, MVP) ---
109+
110+
type WorkflowSpec struct {
111+
Description string `yaml:"description,omitempty" json:"description,omitempty"`
112+
Trigger *WorkflowTrigger `yaml:"trigger,omitempty" json:"trigger,omitempty"`
113+
Input *WorkflowInput `yaml:"input,omitempty" json:"input,omitempty"`
114+
Policy string `yaml:"policy,omitempty" json:"policy,omitempty"`
115+
Steps []WorkflowStep `yaml:"steps,omitempty" json:"steps,omitempty"`
116+
Output *WorkflowOutput `yaml:"output,omitempty" json:"output,omitempty"`
117+
}
118+
119+
type WorkflowTrigger struct {
120+
Type string `yaml:"type,omitempty" json:"type,omitempty"`
121+
}
122+
123+
type WorkflowInput struct {
124+
Schema string `yaml:"schema,omitempty" json:"schema,omitempty"`
125+
}
126+
127+
type WorkflowStep struct {
128+
ID string `yaml:"id,omitempty" json:"id,omitempty"`
129+
Uses string `yaml:"uses,omitempty" json:"uses,omitempty"`
130+
Agent string `yaml:"agent,omitempty" json:"agent,omitempty"`
131+
With map[string]any `yaml:"with,omitempty" json:"with,omitempty"`
132+
}
133+
134+
type WorkflowOutput struct {
135+
Value map[string]any `yaml:"value,omitempty" json:"value,omitempty"`
136+
}
137+
138+
// --- Policy (design doc §7.5, MVP) ---
139+
140+
type PolicySpec struct {
141+
Execution *PolicyExecution `yaml:"execution,omitempty" json:"execution,omitempty"`
142+
Tools *PolicyTools `yaml:"tools,omitempty" json:"tools,omitempty"`
143+
Approvals *PolicyApprovals `yaml:"approvals,omitempty" json:"approvals,omitempty"`
144+
Security *PolicySecurity `yaml:"security,omitempty" json:"security,omitempty"`
145+
}
146+
147+
type PolicyExecution struct {
148+
MaxWallClockSeconds int `yaml:"maxWallClockSeconds,omitempty" json:"maxWallClockSeconds,omitempty"`
149+
MaxTotalCostUsd float64 `yaml:"maxTotalCostUsd,omitempty" json:"maxTotalCostUsd,omitempty"`
150+
RequireStructuredOutput bool `yaml:"requireStructuredOutput,omitempty" json:"requireStructuredOutput,omitempty"`
151+
}
152+
153+
type PolicyTools struct {
154+
ForbidUnknownTools bool `yaml:"forbidUnknownTools,omitempty" json:"forbidUnknownTools,omitempty"`
155+
}
156+
157+
type PolicyApprovals struct {
158+
RequiredFor []string `yaml:"requiredFor,omitempty" json:"requiredFor,omitempty"`
159+
}
160+
161+
type PolicySecurity struct {
162+
NetworkAccess string `yaml:"networkAccess,omitempty" json:"networkAccess,omitempty"`
163+
SecretAccess string `yaml:"secretAccess,omitempty" json:"secretAccess,omitempty"`
164+
}
165+
166+
// --- Environment (design doc §7.6, MVP overrides) ---
167+
168+
type EnvironmentSpec struct {
169+
Overrides *EnvironmentOverrides `yaml:"overrides,omitempty" json:"overrides,omitempty"`
170+
}
171+
172+
type EnvironmentOverrides struct {
173+
Agents map[string]AgentOverride `yaml:"agents,omitempty" json:"agents,omitempty"`
174+
Policies map[string]PolicyOverride `yaml:"policies,omitempty" json:"policies,omitempty"`
175+
}
176+
177+
type AgentOverride struct {
178+
Model string `yaml:"model,omitempty" json:"model,omitempty"`
179+
Constraints *AgentConstraints `yaml:"constraints,omitempty" json:"constraints,omitempty"`
180+
}
181+
182+
type PolicyOverride struct {
183+
Execution *PolicyExecution `yaml:"execution,omitempty" json:"execution,omitempty"`
184+
}

internal/spec/types.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package spec
2+
3+
// API version for MVP resources (design doc §6.1).
4+
const APIVersionV0 = "agentic.dev/v0"
5+
6+
// Kind names for MVP resources (design doc §6.2).
7+
const (
8+
KindProject = "Project"
9+
KindAgent = "Agent"
10+
KindTool = "Tool"
11+
KindWorkflow = "Workflow"
12+
KindPolicy = "Policy"
13+
KindEnvironment = "Environment"
14+
)
15+
16+
// Metadata is shared resource metadata (design doc §6.1).
17+
type Metadata struct {
18+
Name string `yaml:"name" json:"name"`
19+
Labels map[string]string `yaml:"labels,omitempty" json:"labels,omitempty"`
20+
Annotations map[string]string `yaml:"annotations,omitempty" json:"annotations,omitempty"`
21+
}
22+
23+
// ResourceID identifies a resource by kind and metadata name (design doc §12.2).
24+
type ResourceID struct {
25+
Kind string `yaml:"kind" json:"kind"`
26+
Name string `yaml:"name" json:"name"`
27+
}
28+
29+
// String returns a stable identifier for logs and display (e.g. "Agent/reviewer").
30+
func (r ResourceID) String() string {
31+
return r.Kind + "/" + r.Name
32+
}
33+
34+
// Resource is the apiVersion/kind/metadata/spec envelope for a typed spec (design doc §6.1).
35+
type Resource[T any] struct {
36+
APIVersion string `yaml:"apiVersion" json:"apiVersion"`
37+
Kind string `yaml:"kind" json:"kind"`
38+
Metadata Metadata `yaml:"metadata" json:"metadata"`
39+
Spec T `yaml:"spec" json:"spec"`
40+
}
41+
42+
// MVP resource envelopes with concrete spec types.
43+
type (
44+
ProjectResource = Resource[ProjectSpec]
45+
AgentResource = Resource[AgentSpec]
46+
ToolResource = Resource[ToolSpec]
47+
WorkflowResource = Resource[WorkflowSpec]
48+
PolicyResource = Resource[PolicySpec]
49+
EnvironmentResource = Resource[EnvironmentSpec]
50+
)
51+
52+
// ProjectGraph is the merged in-memory view keyed by resource name (design doc §12.2).
53+
type ProjectGraph struct {
54+
Meta Metadata `yaml:"-" json:"-"`
55+
Spec ProjectSpec
56+
Agents map[string]*AgentResource
57+
Tools map[string]*ToolResource
58+
Workflows map[string]*WorkflowResource
59+
Policies map[string]*PolicyResource
60+
Environments map[string]*EnvironmentResource
61+
}

0 commit comments

Comments
 (0)