Skip to content

Commit 51d1d2e

Browse files
committed
Merge branch 'main' into pr/inFocus7/821
* main: Fix UI/streaming timeouts for long running LLM requests (#907) fix helm value for env (#910) feat: allow per-agent header configuration for tools (#884) feat: Set system message from ConfigMap or Secrets (#894)
2 parents 594c639 + 2b5ea5c commit 51d1d2e

25 files changed

Lines changed: 1175 additions & 190 deletions

Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,11 @@ build-img-versions:
182182
@echo app=$(APP_IMG)
183183
@echo kagent-adk=$(KAGENT_ADK_IMG)
184184

185+
.PHONY: lint
186+
lint:
187+
make -C go lint
188+
make -C python lint
189+
185190
.PHONY: push
186191
push: push-controller push-ui push-app push-kagent-adk
187192

go/api/v1alpha2/agent_types.go

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,13 @@ limitations under the License.
1717
package v1alpha2
1818

1919
import (
20+
"context"
21+
"fmt"
22+
2023
corev1 "k8s.io/api/core/v1"
2124
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2225
"k8s.io/apimachinery/pkg/runtime/schema"
26+
"sigs.k8s.io/controller-runtime/pkg/client"
2327

2428
"trpc.group/trpc-go/trpc-a2a-go/server"
2529
)
@@ -54,9 +58,14 @@ type AgentSpec struct {
5458
Description string `json:"description,omitempty"`
5559
}
5660

61+
// +kubebuilder:validation:XValidation:rule="!has(self.systemMessage) || !has(self.systemMessageFrom)",message="systemMessage and systemMessageFrom are mutually exclusive"
5762
type DeclarativeAgentSpec struct {
58-
// +kubebuilder:validation:MinLength=1
63+
// SystemMessage is a string specifying the system message for the agent
64+
// +optional
5965
SystemMessage string `json:"systemMessage,omitempty"`
66+
// SystemMessageFrom is a reference to a ConfigMap or Secret containing the system message.
67+
// +optional
68+
SystemMessageFrom *ValueSource `json:"systemMessageFrom,omitempty"`
6069
// The name of the model config to use.
6170
// If not specified, the default value is "default-model-config".
6271
// Must be in the same namespace as the Agent.
@@ -154,6 +163,29 @@ type Tool struct {
154163
McpServer *McpServerTool `json:"mcpServer,omitempty"`
155164
// +optional
156165
Agent *TypedLocalReference `json:"agent,omitempty"`
166+
167+
// HeadersFrom specifies a list of configuration values to be added as
168+
// headers to requests sent to the Tool from this agent. The value of
169+
// each header is resolved from either a Secret or ConfigMap in the same
170+
// namespace as the Agent. Headers specified here will override any
171+
// headers of the same name/key specified on the tool.
172+
// +optional
173+
HeadersFrom []ValueRef `json:"headersFrom,omitempty"`
174+
}
175+
176+
func (s *Tool) ResolveHeaders(ctx context.Context, client client.Client, namespace string) (map[string]string, error) {
177+
result := map[string]string{}
178+
179+
for _, h := range s.HeadersFrom {
180+
k, v, err := h.Resolve(ctx, client, namespace)
181+
if err != nil {
182+
return nil, fmt.Errorf("failed to resolve header: %v", err)
183+
}
184+
185+
result[k] = v
186+
}
187+
188+
return result, nil
157189
}
158190

159191
type McpServerTool struct {

go/api/v1alpha2/common_types.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
Copyright 2025.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1alpha2
18+
19+
import (
20+
"context"
21+
"fmt"
22+
23+
"github.com/kagent-dev/kagent/go/internal/utils"
24+
"k8s.io/apimachinery/pkg/types"
25+
"sigs.k8s.io/controller-runtime/pkg/client"
26+
)
27+
28+
type ValueSourceType string
29+
30+
const (
31+
ConfigMapValueSource ValueSourceType = "ConfigMap"
32+
SecretValueSource ValueSourceType = "Secret"
33+
)
34+
35+
// ValueSource defines a source for configuration values from a Secret or ConfigMap
36+
type ValueSource struct {
37+
// +kubebuilder:validation:Enum=ConfigMap;Secret
38+
Type ValueSourceType `json:"type"`
39+
// The name of the ConfigMap or Secret.
40+
Name string `json:"name"`
41+
// The key of the ConfigMap or Secret.
42+
Key string `json:"key"`
43+
}
44+
45+
func (s *ValueSource) Resolve(ctx context.Context, client client.Client, namespace string) (string, error) {
46+
if s == nil {
47+
return "", fmt.Errorf("ValueSource cannot be nil")
48+
}
49+
50+
switch s.Type {
51+
case ConfigMapValueSource:
52+
return utils.GetConfigMapValue(ctx, client, types.NamespacedName{Namespace: namespace, Name: s.Name}, s.Key)
53+
case SecretValueSource:
54+
return utils.GetSecretValue(ctx, client, types.NamespacedName{Namespace: namespace, Name: s.Name}, s.Key)
55+
default:
56+
return "", fmt.Errorf("unknown value source type: %s", s.Type)
57+
}
58+
}
59+
60+
// ValueRef represents a configuration value
61+
// +kubebuilder:validation:XValidation:rule="(has(self.value) && !has(self.valueFrom)) || (!has(self.value) && has(self.valueFrom))",message="Exactly one of value or valueFrom must be specified"
62+
type ValueRef struct {
63+
Name string `json:"name"`
64+
// +optional
65+
Value string `json:"value,omitempty"`
66+
// +optional
67+
ValueFrom *ValueSource `json:"valueFrom,omitempty"`
68+
}
69+
70+
func (r *ValueRef) Resolve(ctx context.Context, client client.Client, namespace string) (string, string, error) {
71+
if r == nil {
72+
return "", "", fmt.Errorf("ValueRef cannot be nil")
73+
}
74+
75+
switch {
76+
case r.Value != "":
77+
return r.Name, r.Value, nil
78+
case r.ValueFrom != nil:
79+
value, err := r.ValueFrom.Resolve(ctx, client, namespace)
80+
if err != nil {
81+
return "", "", fmt.Errorf("failed to resolve value for ref %s: %v", r.Name, err)
82+
}
83+
84+
return r.Name, value, nil
85+
default:
86+
return r.Name, "", nil
87+
}
88+
}

go/api/v1alpha2/remotemcpserver_types.go

Lines changed: 0 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,7 @@ import (
2323
"encoding/json"
2424
"fmt"
2525

26-
"github.com/kagent-dev/kagent/go/internal/utils"
2726
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28-
"k8s.io/apimachinery/pkg/types"
2927
"sigs.k8s.io/controller-runtime/pkg/client"
3028
)
3129

@@ -87,68 +85,6 @@ func (t RemoteMCPServerSpec) Value() (driver.Value, error) {
8785
return json.Marshal(t)
8886
}
8987

90-
type ValueSourceType string
91-
92-
const (
93-
ConfigMapValueSource ValueSourceType = "ConfigMap"
94-
SecretValueSource ValueSourceType = "Secret"
95-
)
96-
97-
// ValueSource defines a source for configuration values from a Secret or ConfigMap
98-
type ValueSource struct {
99-
// +kubebuilder:validation:Enum=ConfigMap;Secret
100-
Type ValueSourceType `json:"type"`
101-
// The name of the ConfigMap or Secret.
102-
Name string `json:"name"`
103-
// The key of the ConfigMap or Secret.
104-
Key string `json:"key"`
105-
}
106-
107-
func (s *ValueSource) Resolve(ctx context.Context, client client.Client, namespace string) (string, error) {
108-
if s == nil {
109-
return "", fmt.Errorf("ValueSource cannot be nil")
110-
}
111-
112-
switch s.Type {
113-
case ConfigMapValueSource:
114-
return utils.GetConfigMapValue(ctx, client, types.NamespacedName{Namespace: namespace, Name: s.Name}, s.Key)
115-
case SecretValueSource:
116-
return utils.GetSecretValue(ctx, client, types.NamespacedName{Namespace: namespace, Name: s.Name}, s.Key)
117-
default:
118-
return "", fmt.Errorf("unknown value source type: %s", s.Type)
119-
}
120-
}
121-
122-
// ValueRef represents a configuration value
123-
// +kubebuilder:validation:XValidation:rule="(has(self.value) && !has(self.valueFrom)) || (!has(self.value) && has(self.valueFrom))",message="Exactly one of value or valueFrom must be specified"
124-
type ValueRef struct {
125-
Name string `json:"name"`
126-
// +optional
127-
Value string `json:"value,omitempty"`
128-
// +optional
129-
ValueFrom *ValueSource `json:"valueFrom,omitempty"`
130-
}
131-
132-
func (r *ValueRef) Resolve(ctx context.Context, client client.Client, namespace string) (string, string, error) {
133-
if r == nil {
134-
return "", "", fmt.Errorf("ValueRef cannot be nil")
135-
}
136-
137-
switch {
138-
case r.Value != "":
139-
return r.Name, r.Value, nil
140-
case r.ValueFrom != nil:
141-
value, err := r.ValueFrom.Resolve(ctx, client, namespace)
142-
if err != nil {
143-
return "", "", fmt.Errorf("failed to resolve value for ref %s: %v", r.Name, err)
144-
}
145-
146-
return r.Name, value, nil
147-
default:
148-
return r.Name, "", nil
149-
}
150-
}
151-
15288
// RemoteMCPServerStatus defines the observed state of RemoteMCPServer.
15389
type RemoteMCPServerStatus struct {
15490
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster

go/api/v1alpha2/zz_generated.deepcopy.go

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

go/config/crd/bases/kagent.dev_agents.yaml

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6781,6 +6781,26 @@ spec:
67816781
systemMessage:
67826782
minLength: 1
67836783
type: string
6784+
systemMessageFrom:
6785+
description: SystemMessageFrom is a reference to a ConfigMap or
6786+
Secret containing the system message.
6787+
properties:
6788+
key:
6789+
description: The key of the ConfigMap or Secret.
6790+
type: string
6791+
name:
6792+
description: The name of the ConfigMap or Secret.
6793+
type: string
6794+
type:
6795+
enum:
6796+
- ConfigMap
6797+
- Secret
6798+
type: string
6799+
required:
6800+
- key
6801+
- name
6802+
- type
6803+
type: object
67846804
tools:
67856805
items:
67866806
properties:
@@ -6795,6 +6815,48 @@ spec:
67956815
required:
67966816
- name
67976817
type: object
6818+
headersFrom:
6819+
description: |-
6820+
HeadersFrom specifies a list of configuration values to be added as
6821+
headers to requests sent to the Tool from this agent. The value of
6822+
each header is resolved from either a Secret or ConfigMap in the same
6823+
namespace as the Agent. Headers specified here will override any
6824+
headers of the same name/key specified on the tool.
6825+
items:
6826+
description: ValueRef represents a configuration value
6827+
properties:
6828+
name:
6829+
type: string
6830+
value:
6831+
type: string
6832+
valueFrom:
6833+
description: ValueSource defines a source for configuration
6834+
values from a Secret or ConfigMap
6835+
properties:
6836+
key:
6837+
description: The key of the ConfigMap or Secret.
6838+
type: string
6839+
name:
6840+
description: The name of the ConfigMap or Secret.
6841+
type: string
6842+
type:
6843+
enum:
6844+
- ConfigMap
6845+
- Secret
6846+
type: string
6847+
required:
6848+
- key
6849+
- name
6850+
- type
6851+
type: object
6852+
required:
6853+
- name
6854+
type: object
6855+
x-kubernetes-validations:
6856+
- message: Exactly one of value or valueFrom must be specified
6857+
rule: (has(self.value) && !has(self.valueFrom)) || (!has(self.value)
6858+
&& has(self.valueFrom))
6859+
type: array
67986860
mcpServer:
67996861
properties:
68006862
apiGroup:
@@ -6838,6 +6900,9 @@ spec:
68386900
maxItems: 20
68396901
type: array
68406902
type: object
6903+
x-kubernetes-validations:
6904+
- message: systemMessage and systemMessageFrom are mutually exclusive
6905+
rule: '!has(self.systemMessage) || !has(self.systemMessageFrom)'
68416906
description:
68426907
type: string
68436908
remote:

0 commit comments

Comments
 (0)