From 4e8b4a66c6ff1dedf90d6f00fbc05ae04903c03f Mon Sep 17 00:00:00 2001
From: Ubuntu
Date: Fri, 1 May 2026 08:13:21 +0000
Subject: [PATCH] feat(agnet): persist runtime_execution and sk_access_policy
with validation
Go control plane: extend agent plan structs, validate bindings and SK policy
codes. Web: surface bindings on Agents page with i18n.
Made-with: Cursor
---
heicode/controller/agnet_control_plane.go | 61 +++++++++++-
.../default/src/features/agnet-console/api.ts | 16 ++++
.../src/features/agnet-console/pages.tsx | 96 +++++++++++++++++++
heicode/web/default/src/i18n/locales/en.json | 8 ++
heicode/web/default/src/i18n/locales/fr.json | 8 ++
heicode/web/default/src/i18n/locales/ja.json | 8 ++
heicode/web/default/src/i18n/locales/ru.json | 8 ++
heicode/web/default/src/i18n/locales/vi.json | 8 ++
heicode/web/default/src/i18n/locales/zh.json | 8 ++
9 files changed, 217 insertions(+), 4 deletions(-)
diff --git a/heicode/controller/agnet_control_plane.go b/heicode/controller/agnet_control_plane.go
index 43953a5..deefb86 100644
--- a/heicode/controller/agnet_control_plane.go
+++ b/heicode/controller/agnet_control_plane.go
@@ -27,11 +27,27 @@ type agnetSKSource struct {
ArtifactID string `json:"artifact_id"`
}
+// agnetRuntimeExecution mirrors docs/integration/agnet-platform-api-design.md §5.0 (runtime_execution).
+type agnetRuntimeExecution struct {
+ ProfileID string `json:"profile_id"`
+ CloudPrincipalRefs []string `json:"cloud_principal_refs"`
+ NetworkPolicyRef string `json:"network_policy_ref"`
+}
+
+// agnetSKAccessPolicy mirrors docs/integration/agnet-platform-api-design.md §5.0 (sk_access_policy).
+type agnetSKAccessPolicy struct {
+ PolicyRef string `json:"policy_ref"`
+ DenySkillIDs []string `json:"deny_skill_ids"`
+ InheritDeploymentDefaults bool `json:"inherit_deployment_defaults"`
+}
+
type agnetAgentPlan struct {
- RoleTemplate string `json:"role_template"`
- Goal string `json:"goal"`
- DefaultModelID string `json:"default_model_id"`
- SKSources []agnetSKSource `json:"sk_sources"`
+ RoleTemplate string `json:"role_template"`
+ Goal string `json:"goal"`
+ DefaultModelID string `json:"default_model_id"`
+ SKSources []agnetSKSource `json:"sk_sources"`
+ RuntimeExecution agnetRuntimeExecution `json:"runtime_execution"`
+ SKAccessPolicy agnetSKAccessPolicy `json:"sk_access_policy"`
}
type agnetConstraints struct {
@@ -132,6 +148,37 @@ func containsString(values []string, target string) bool {
return false
}
+func agnetRuntimePartiallySet(r agnetRuntimeExecution) bool {
+ return strings.TrimSpace(r.ProfileID) != "" ||
+ len(r.CloudPrincipalRefs) > 0 ||
+ strings.TrimSpace(r.NetworkPolicyRef) != ""
+}
+
+func validateAgentRuntimeBindings(c *gin.Context, agent agnetAgentPlan) bool {
+ r := agent.RuntimeExecution
+ if !agnetRuntimePartiallySet(r) {
+ return true
+ }
+ if strings.TrimSpace(r.ProfileID) == "" {
+ agnetError(c, "RUNTIME_BINDING_INVALID", "runtime_execution.profile_id is required when runtime bindings are present")
+ return false
+ }
+ return true
+}
+
+func validateAgentSKAccessPolicy(c *gin.Context, agent agnetAgentPlan) bool {
+ p := agent.SKAccessPolicy
+ hasDeny := len(p.DenySkillIDs) > 0
+ if !hasDeny {
+ return true
+ }
+ if strings.TrimSpace(p.PolicyRef) == "" && !p.InheritDeploymentDefaults {
+ agnetError(c, "SK_POLICY_REJECTED", "sk_access_policy.policy_ref or inherit_deployment_defaults is required when deny_skill_ids is set")
+ return false
+ }
+ return true
+}
+
func validateOrchestrationPlan(c *gin.Context, plan agnetOrchestrationPlan) bool {
if strings.TrimSpace(plan.IntentID) == "" ||
strings.TrimSpace(plan.TemplateHint) == "" ||
@@ -187,6 +234,12 @@ func validateOrchestrationPlan(c *gin.Context, plan agnetOrchestrationPlan) bool
agnetError(c, "MODEL_NOT_ALLOWED", "agent default_model_id is outside allowed_model_ids")
return false
}
+ if !validateAgentRuntimeBindings(c, agent) {
+ return false
+ }
+ if !validateAgentSKAccessPolicy(c, agent) {
+ return false
+ }
}
return true
diff --git a/heicode/web/default/src/features/agnet-console/api.ts b/heicode/web/default/src/features/agnet-console/api.ts
index 7e2781f..0889116 100644
--- a/heicode/web/default/src/features/agnet-console/api.ts
+++ b/heicode/web/default/src/features/agnet-console/api.ts
@@ -1,5 +1,19 @@
import { api } from '@/lib/api'
+/** Sub-agent cloud/runtime binding (passed to Agnet on deploy). */
+export type AgnetRuntimeExecution = {
+ profile_id?: string
+ cloud_principal_refs?: string[]
+ network_policy_ref?: string
+}
+
+/** SK allow/deny policy attached to the agent in the deployment plan. */
+export type AgnetSKAccessPolicy = {
+ policy_ref?: string
+ deny_skill_ids?: string[]
+ inherit_deployment_defaults?: boolean
+}
+
export type AgnetDeployment = {
deployment_id: string
status: string
@@ -14,6 +28,8 @@ export type AgnetDeployment = {
goal?: string
default_model_id?: string
sk_sources?: Array<{ type?: string; artifact_id?: string }>
+ runtime_execution?: AgnetRuntimeExecution
+ sk_access_policy?: AgnetSKAccessPolicy
}>
metadata?: {
tenant_id?: string
diff --git a/heicode/web/default/src/features/agnet-console/pages.tsx b/heicode/web/default/src/features/agnet-console/pages.tsx
index 3bc0348..5333505 100644
--- a/heicode/web/default/src/features/agnet-console/pages.tsx
+++ b/heicode/web/default/src/features/agnet-console/pages.tsx
@@ -42,6 +42,8 @@ import {
getAgnetSnapshots,
listAgnetDeployments,
type AgnetDeployment,
+ type AgnetRuntimeExecution,
+ type AgnetSKAccessPolicy,
} from './api'
type StatusKey = 'running' | 'success' | 'failed' | 'pending'
@@ -820,6 +822,24 @@ export function AgnetTemplatesPage() {
)
}
+function runtimeSummary(rt: AgnetRuntimeExecution | undefined): boolean {
+ if (!rt) return false
+ return Boolean(
+ (rt.profile_id && rt.profile_id.trim() !== '') ||
+ (rt.cloud_principal_refs && rt.cloud_principal_refs.length > 0) ||
+ (rt.network_policy_ref && rt.network_policy_ref.trim() !== '')
+ )
+}
+
+function policySummary(p: AgnetSKAccessPolicy | undefined): boolean {
+ if (!p) return false
+ return Boolean(
+ (p.policy_ref && p.policy_ref.trim() !== '') ||
+ (p.deny_skill_ids && p.deny_skill_ids.length > 0) ||
+ p.inherit_deployment_defaults
+ )
+}
+
export function AgnetAgentsPage() {
const { t } = useTranslation()
const { data = [] } = useQuery({
@@ -835,6 +855,8 @@ export function AgnetAgentsPage() {
role: agent.role_template || '-',
model: agent.default_model_id || '-',
goal: agent.goal || '-',
+ runtime: agent.runtime_execution,
+ skPolicy: agent.sk_access_policy,
}))
),
[data]
@@ -861,6 +883,80 @@ export function AgnetAgentsPage() {
{row.dep} · model: {row.model}
{row.goal}
+ {runtimeSummary(row.runtime) && (
+
+
+ {t('Runtime binding')}
+
+ {row.runtime?.profile_id ? (
+
+
+ {t('Execution profile')}
+ :{' '}
+
+
+ {row.runtime.profile_id}
+
+
+ ) : null}
+ {(row.runtime?.cloud_principal_refs?.length ?? 0) > 0 ? (
+
+
+ {t('Cloud principals')}
+ :{' '}
+
+
+ {row.runtime?.cloud_principal_refs?.join(', ')}
+
+
+ ) : null}
+ {row.runtime?.network_policy_ref ? (
+
+
+ {t('Network policy')}
+ :{' '}
+
+
+ {row.runtime.network_policy_ref}
+
+
+ ) : null}
+
+ )}
+ {policySummary(row.skPolicy) && (
+
+
+ {t('SK access policy')}
+
+ {row.skPolicy?.policy_ref ? (
+
+
+ {t('Policy ref')}
+ :{' '}
+
+
+ {row.skPolicy.policy_ref}
+
+
+ ) : null}
+ {(row.skPolicy?.deny_skill_ids?.length ?? 0) > 0 ? (
+
+
+ {t('Denied skills')}
+ :{' '}
+
+
+ {row.skPolicy?.deny_skill_ids?.join(', ')}
+
+
+ ) : null}
+ {row.skPolicy?.inherit_deployment_defaults ? (
+
+ {t('Inherits deployment defaults')}
+
+ ) : null}
+
+ )}
))}
diff --git a/heicode/web/default/src/i18n/locales/en.json b/heicode/web/default/src/i18n/locales/en.json
index 2956a5d..a4b3517 100644
--- a/heicode/web/default/src/i18n/locales/en.json
+++ b/heicode/web/default/src/i18n/locales/en.json
@@ -201,6 +201,14 @@
"Agent ID *": "Agent ID *",
"Agentic development control plane": "Agentic development control plane",
"Agents": "Agents",
+ "Runtime binding": "Runtime binding",
+ "SK access policy": "SK access policy",
+ "Execution profile": "Execution profile",
+ "Cloud principals": "Cloud principals",
+ "Network policy": "Network policy",
+ "Policy ref": "Policy ref",
+ "Denied skills": "Denied skills",
+ "Inherits deployment defaults": "Inherits deployment defaults",
"Aggregated usage metrics and trend charts.": "Aggregated usage metrics and trend charts.",
"aggregates 50+ AI providers behind one unified API. Manage access, track costs, and scale effortlessly.": "aggregates 50+ AI providers behind one unified API. Manage access, track costs, and scale effortlessly.",
"Agile Minimal": "Agile Minimal",
diff --git a/heicode/web/default/src/i18n/locales/fr.json b/heicode/web/default/src/i18n/locales/fr.json
index 05504ec..ba5b6bf 100644
--- a/heicode/web/default/src/i18n/locales/fr.json
+++ b/heicode/web/default/src/i18n/locales/fr.json
@@ -201,6 +201,14 @@
"Agent ID *": "ID d'agent *",
"Agentic development control plane": "Agentic development control plane",
"Agents": "Agents",
+ "Runtime binding": "Runtime binding",
+ "SK access policy": "SK access policy",
+ "Execution profile": "Execution profile",
+ "Cloud principals": "Cloud principals",
+ "Network policy": "Network policy",
+ "Policy ref": "Policy ref",
+ "Denied skills": "Denied skills",
+ "Inherits deployment defaults": "Inherits deployment defaults",
"Aggregated usage metrics and trend charts.": "Métriques d'utilisation agrégées et graphiques de tendances.",
"aggregates 50+ AI providers behind one unified API. Manage access, track costs, and scale effortlessly.": "agrège plus de 50 fournisseurs IA derrière une API unifiée. Gérez l'accès, suivez les coûts et évoluez sans effort.",
"Agile Minimal": "Agile Minimal",
diff --git a/heicode/web/default/src/i18n/locales/ja.json b/heicode/web/default/src/i18n/locales/ja.json
index 913c241..82e032d 100644
--- a/heicode/web/default/src/i18n/locales/ja.json
+++ b/heicode/web/default/src/i18n/locales/ja.json
@@ -201,6 +201,14 @@
"Agent ID *": "エージェントID *",
"Agentic development control plane": "Agentic development control plane",
"Agents": "Agents",
+ "Runtime binding": "Runtime binding",
+ "SK access policy": "SK access policy",
+ "Execution profile": "Execution profile",
+ "Cloud principals": "Cloud principals",
+ "Network policy": "Network policy",
+ "Policy ref": "Policy ref",
+ "Denied skills": "Denied skills",
+ "Inherits deployment defaults": "Inherits deployment defaults",
"Aggregated usage metrics and trend charts.": "集計された使用量メトリクスとトレンドチャート。",
"aggregates 50+ AI providers behind one unified API. Manage access, track costs, and scale effortlessly.": "50以上のAIプロバイダーを統一APIで集約。アクセス管理、コスト追跡、スケーリングを簡単に。",
"Agile Minimal": "Agile Minimal",
diff --git a/heicode/web/default/src/i18n/locales/ru.json b/heicode/web/default/src/i18n/locales/ru.json
index eaf32cb..dffb512 100644
--- a/heicode/web/default/src/i18n/locales/ru.json
+++ b/heicode/web/default/src/i18n/locales/ru.json
@@ -201,6 +201,14 @@
"Agent ID *": "Идентификатор агента *",
"Agentic development control plane": "Agentic development control plane",
"Agents": "Agents",
+ "Runtime binding": "Runtime binding",
+ "SK access policy": "SK access policy",
+ "Execution profile": "Execution profile",
+ "Cloud principals": "Cloud principals",
+ "Network policy": "Network policy",
+ "Policy ref": "Policy ref",
+ "Denied skills": "Denied skills",
+ "Inherits deployment defaults": "Inherits deployment defaults",
"Aggregated usage metrics and trend charts.": "Агрегированные метрики использования и графики трендов.",
"aggregates 50+ AI providers behind one unified API. Manage access, track costs, and scale effortlessly.": "объединяет 50+ ИИ-провайдеров за единым API. Управляйте доступом, отслеживайте затраты и масштабируйтесь без усилий.",
"Agile Minimal": "Agile Minimal",
diff --git a/heicode/web/default/src/i18n/locales/vi.json b/heicode/web/default/src/i18n/locales/vi.json
index 2dd828c..b720127 100644
--- a/heicode/web/default/src/i18n/locales/vi.json
+++ b/heicode/web/default/src/i18n/locales/vi.json
@@ -201,6 +201,14 @@
"Agent ID *": "Mã đại lý *",
"Agentic development control plane": "Agentic development control plane",
"Agents": "Agents",
+ "Runtime binding": "Runtime binding",
+ "SK access policy": "SK access policy",
+ "Execution profile": "Execution profile",
+ "Cloud principals": "Cloud principals",
+ "Network policy": "Network policy",
+ "Policy ref": "Policy ref",
+ "Denied skills": "Denied skills",
+ "Inherits deployment defaults": "Inherits deployment defaults",
"Aggregated usage metrics and trend charts.": "Chỉ số sử dụng tổng hợp và biểu đồ xu hướng.",
"aggregates 50+ AI providers behind one unified API. Manage access, track costs, and scale effortlessly.": "tổng hợp hơn 50 nhà cung cấp AI sau một API thống nhất. Quản lý truy cập, theo dõi chi phí và mở rộng dễ dàng.",
"Agile Minimal": "Agile Minimal",
diff --git a/heicode/web/default/src/i18n/locales/zh.json b/heicode/web/default/src/i18n/locales/zh.json
index f420015..2b32773 100644
--- a/heicode/web/default/src/i18n/locales/zh.json
+++ b/heicode/web/default/src/i18n/locales/zh.json
@@ -201,6 +201,14 @@
"Agent ID *": "代理 ID *",
"Agentic development control plane": "智能体研发控制面",
"Agents": "Agent",
+ "Runtime binding": "运行时绑定",
+ "SK access policy": "SK 访问策略",
+ "Execution profile": "执行档案",
+ "Cloud principals": "云身份引用",
+ "Network policy": "网络策略",
+ "Policy ref": "策略引用",
+ "Denied skills": "禁止的技能",
+ "Inherits deployment defaults": "继承部署默认策略",
"Aggregated usage metrics and trend charts.": "聚合使用指标和趋势图表。",
"aggregates 50+ AI providers behind one unified API. Manage access, track costs, and scale effortlessly.": "聚合 50+ AI 提供商于统一 API 之后。轻松管理访问、追踪成本、弹性扩展。",
"Agile Minimal": "敏捷最小编队",