feat(bedrock): auto-seed provider from BEDROCK_CONFIG_PATH on startup

- Add Name field to ProviderConfig; YAML name: key sets the provider
  name shown in the UI (e.g. glm_flash)
- Add SeedDefaultProviders to ProviderController: upserts the Bedrock
  provider into the DB for all existing users at startup and lazily for
  new users on their first Settings page visit
- Editing the YAML and restarting PentAGI automatically propagates new
  values with no UI interaction required
- Simplify to a single BEDROCK_CONFIG_PATH variable: compose uses it as
  the host-side volume mount path and translates it to the fixed
  container path via :+ substitution, eliminating PENTAGI_BEDROCK_CONFIG_PATH
- Fix bedrock_test.go: pass &config.Config{} to DefaultProviderConfig
  after its signature was updated to accept a config argument

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
salecharohit
2026-04-06 15:19:54 +05:30
co-authored by Claude Sonnet 4.6
parent b1b606df7a
commit 264116827d
7 changed files with 82 additions and 11 deletions
+1 -2
View File
@@ -26,7 +26,7 @@ BEDROCK_ACCESS_KEY_ID=
BEDROCK_SECRET_ACCESS_KEY=
BEDROCK_SESSION_TOKEN=
BEDROCK_SERVER_URL=
BEDROCK_CONFIG_PATH= # Optional: set to /opt/pentagi/conf/bedrock.provider.yml when using PENTAGI_BEDROCK_CONFIG_PATH below
BEDROCK_CONFIG_PATH= # Optional: path to a custom YAML provider config on the host (e.g. ./glm_flash_bedrock.yml next to docker-compose.yml); the name field inside the YAML sets the provider name in the UI
## DeepSeek LLM provider
DEEPSEEK_API_KEY=
@@ -138,7 +138,6 @@ PENTAGI_DOCKER_SOCKET=
PENTAGI_DOCKER_CERT_PATH=
PENTAGI_LLM_SERVER_CONFIG_PATH=
PENTAGI_OLLAMA_SERVER_CONFIG_PATH=
PENTAGI_BEDROCK_CONFIG_PATH= # Host path to a custom Bedrock provider config YAML (e.g. ./glm_flash_bedrock.yml from the repo root); mounted into the container at /opt/pentagi/conf/bedrock.provider.yml
## PentAGI security settings
PUBLIC_URL=https://localhost:8443
+4
View File
@@ -1695,6 +1695,10 @@ func (r *queryResolver) SettingsProviders(ctx context.Context) (*model.Providers
"uid": uid,
}).Debug("get providers")
if err := r.ProvidersCtrl.SeedDefaultProviders(ctx, uid); err != nil {
r.Logger.WithError(err).Warn("failed to seed default providers")
}
config := model.ProvidersConfig{
Enabled: &model.ProvidersReadinessStatus{},
Default: &model.DefaultProvidersConfig{},
@@ -21,7 +21,7 @@ func TestConfigLoading(t *testing.T) {
BedrockSecretKey: "test-key",
}
providerConfig, err := DefaultProviderConfig()
providerConfig, err := DefaultProviderConfig(&config.Config{})
if err != nil {
t.Fatalf("Failed to create provider config: %v", err)
}
@@ -68,7 +68,7 @@ func TestProviderType(t *testing.T) {
BedrockSecretKey: "test-key",
}
providerConfig, err := DefaultProviderConfig()
providerConfig, err := DefaultProviderConfig(&config.Config{})
if err != nil {
t.Fatalf("Failed to create provider config: %v", err)
}
@@ -154,7 +154,7 @@ func TestGetUsage(t *testing.T) {
BedrockSecretKey: "test-key",
}
providerConfig, err := DefaultProviderConfig()
providerConfig, err := DefaultProviderConfig(&config.Config{})
if err != nil {
t.Fatalf("Failed to create provider config: %v", err)
}
@@ -877,7 +877,7 @@ func TestExtractToolsFromOptions(t *testing.T) {
// TestAuthenticationStrategies verifies all supported authentication methods.
func TestAuthenticationStrategies(t *testing.T) {
providerConfig, err := DefaultProviderConfig()
providerConfig, err := DefaultProviderConfig(&config.Config{})
if err != nil {
t.Fatalf("Failed to create provider config: %v", err)
}
@@ -1020,7 +1020,7 @@ func TestAuthenticationStrategies(t *testing.T) {
// TestAuthenticationErrors verifies error handling for invalid configurations.
func TestAuthenticationErrors(t *testing.T) {
providerConfig, err := DefaultProviderConfig()
providerConfig, err := DefaultProviderConfig(&config.Config{})
if err != nil {
t.Fatalf("Failed to create provider config: %v", err)
}
+1
View File
@@ -214,6 +214,7 @@ type AgentConfig struct {
// ProviderConfig represents the configuration for all agents
type ProviderConfig struct {
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Simple *AgentConfig `json:"simple,omitempty" yaml:"simple,omitempty"`
SimpleJSON *AgentConfig `json:"simple_json,omitempty" yaml:"simple_json,omitempty"`
PrimaryAgent *AgentConfig `json:"primary_agent,omitempty" yaml:"primary_agent,omitempty"`
+67 -2
View File
@@ -117,6 +117,8 @@ type ProviderController interface {
prvID int64,
) (database.Provider, error)
SeedDefaultProviders(ctx context.Context, userID int64) error
TestAgent(
ctx context.Context,
prvtype provider.ProviderType,
@@ -353,7 +355,7 @@ func NewProviderController(
graphitiClient = &graphiti.Client{}
}
return &providerController{
pc := &providerController{
db: db,
cfg: cfg,
docker: docker,
@@ -372,7 +374,24 @@ func NewProviderController(
defaultConfigs: defaultConfigs,
Providers: providers,
}, nil
}
// Seed configured system providers into the DB for all existing users so
// they are immediately available without any UI interaction. This runs on
// every startup, so editing a YAML config file and restarting PentAGI
// automatically propagates new values.
ctx := context.Background()
if users, err := db.GetUsers(ctx); err != nil {
logrus.WithError(err).Warn("failed to fetch users for provider seeding")
} else {
for _, u := range users {
if err := pc.SeedDefaultProviders(ctx, u.ID); err != nil {
logrus.WithError(err).Warnf("failed to seed default providers for user %d", u.ID)
}
}
}
return pc, nil
}
func (pc *providerController) NewFlowProvider(
@@ -826,6 +845,52 @@ func (pc *providerController) NewProvider(prv database.Provider) (provider.Provi
}
}
func (pc *providerController) SeedDefaultProviders(ctx context.Context, userID int64) error {
if pc.cfg.BedrockConfig == "" {
return nil
}
if !pc.cfg.BedrockDefaultAuth && pc.cfg.BedrockBearerToken == "" &&
(pc.cfg.BedrockAccessKey == "" || pc.cfg.BedrockSecretKey == "") {
return nil
}
bedrockCfg, ok := pc.defaultConfigs[provider.ProviderBedrock]
if !ok {
return nil
}
rawConfig, err := json.Marshal(bedrockCfg)
if err != nil {
return fmt.Errorf("failed to marshal bedrock config: %w", err)
}
prvname := bedrockCfg.Name
if prvname == "" {
prvname = string(provider.DefaultProviderNameBedrock)
}
existing, err := pc.db.GetUserProviderByName(ctx, database.GetUserProviderByNameParams{
Name: prvname,
UserID: userID,
})
if err != nil {
_, err = pc.db.CreateProvider(ctx, database.CreateProviderParams{
UserID: userID,
Type: database.ProviderType(provider.ProviderBedrock),
Name: prvname,
Config: rawConfig,
})
return err
}
_, err = pc.db.UpdateUserProvider(ctx, database.UpdateUserProviderParams{
ID: existing.ID,
UserID: userID,
Config: rawConfig,
Name: existing.Name,
})
return err
}
func (pc *providerController) CreateProvider(
ctx context.Context,
userID int64,
+2 -2
View File
@@ -55,7 +55,7 @@ services:
- BEDROCK_SECRET_ACCESS_KEY=${BEDROCK_SECRET_ACCESS_KEY:-}
- BEDROCK_SESSION_TOKEN=${BEDROCK_SESSION_TOKEN:-}
- BEDROCK_SERVER_URL=${BEDROCK_SERVER_URL:-}
- BEDROCK_CONFIG_PATH=${BEDROCK_CONFIG_PATH:-}
- BEDROCK_CONFIG_PATH=${BEDROCK_CONFIG_PATH:+/opt/pentagi/conf/bedrock.provider.yml}
- DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY:-}
- DEEPSEEK_SERVER_URL=${DEEPSEEK_SERVER_URL:-}
- DEEPSEEK_PROVIDER=${DEEPSEEK_PROVIDER:-}
@@ -177,7 +177,7 @@ services:
- ${PENTAGI_DOCKER_SOCKET:-/var/run/docker.sock}:/var/run/docker.sock
- ${PENTAGI_LLM_SERVER_CONFIG_PATH:-./example.custom.provider.yml}:/opt/pentagi/conf/custom.provider.yml
- ${PENTAGI_OLLAMA_SERVER_CONFIG_PATH:-./example.ollama.provider.yml}:/opt/pentagi/conf/ollama.provider.yml
- ${PENTAGI_BEDROCK_CONFIG_PATH:-./glm_flash_bedrock.yml}:/opt/pentagi/conf/bedrock.provider.yml
- ${BEDROCK_CONFIG_PATH:-./glm_flash_bedrock.yml}:/opt/pentagi/conf/bedrock.provider.yml
- ${PENTAGI_DOCKER_CERT_PATH:-./docker-ssl}:/opt/pentagi/docker/ssl
user: root:root # while using docker.sock
networks:
+2
View File
@@ -2,6 +2,8 @@
# Exported from the glm_flash provider stored in the database.
# To use, set BEDROCK_CONFIG_PATH=./glm_flash_bedrock.yml in your .env file.
name: glm_flash
simple:
model: zai.glm-4.7-flash
temperature: 0.5