Skip to content

manifest

Class info

Classes

Name Children Inherits
AgentConfig
llmling_agent.models.agents
Configuration for a single agent in the system.
    AgentsManifest
    llmling_agent.models.manifest
    Complete agent configuration manifest defining all available agents.
      BaseProviderConfig
      llmling_agent.models.providers
      Base configuration for agent providers.
      ConversionConfig
      llmling_agent.models.converters
      Global conversion configuration.
        Job
        llmling_agent.models.task
        A task is a piece of work that can be executed by an agent.
          MCPServerBase
          llmling_agent.models.mcp_server
          Base model for MCP server configuration.
          ObservabilityConfig
          llmling_agent.models.observability
          Global observability configuration.
            PoolServerConfig
            llmling_agent.models.mcp_server
            Configuration for pool-based MCP server.
              PromptConfig
              llmling_agent.models.prompts
              Complete prompt configuration.
                StdioMCPServer
                llmling_agent.models.mcp_server
                MCP server started via stdio.
                  StorageConfig
                  llmling_agent.models.storage
                  Global storage configuration.
                    TeamConfig
                    llmling_agent.models.teams
                    Configuration for a team or chain of message nodes.

                      🛈 DocStrings

                      Models for agent configuration.

                      AgentsManifest

                      Bases: ConfigModel

                      Complete agent configuration manifest defining all available agents.

                      This is the root configuration that: - Defines available response types (both inline and imported) - Configures all agent instances and their settings - Sets up custom role definitions and capabilities - Manages environment configurations

                      A single manifest can define multiple agents that can work independently or collaborate through the orchestrator.

                      Source code in src/llmling_agent/models/manifest.py
                       40
                       41
                       42
                       43
                       44
                       45
                       46
                       47
                       48
                       49
                       50
                       51
                       52
                       53
                       54
                       55
                       56
                       57
                       58
                       59
                       60
                       61
                       62
                       63
                       64
                       65
                       66
                       67
                       68
                       69
                       70
                       71
                       72
                       73
                       74
                       75
                       76
                       77
                       78
                       79
                       80
                       81
                       82
                       83
                       84
                       85
                       86
                       87
                       88
                       89
                       90
                       91
                       92
                       93
                       94
                       95
                       96
                       97
                       98
                       99
                      100
                      101
                      102
                      103
                      104
                      105
                      106
                      107
                      108
                      109
                      110
                      111
                      112
                      113
                      114
                      115
                      116
                      117
                      118
                      119
                      120
                      121
                      122
                      123
                      124
                      125
                      126
                      127
                      128
                      129
                      130
                      131
                      132
                      133
                      134
                      135
                      136
                      137
                      138
                      139
                      140
                      141
                      142
                      143
                      144
                      145
                      146
                      147
                      148
                      149
                      150
                      151
                      152
                      153
                      154
                      155
                      156
                      157
                      158
                      159
                      160
                      161
                      162
                      163
                      164
                      165
                      166
                      167
                      168
                      169
                      170
                      171
                      172
                      173
                      174
                      175
                      176
                      177
                      178
                      179
                      180
                      181
                      182
                      183
                      184
                      185
                      186
                      187
                      188
                      189
                      190
                      191
                      192
                      193
                      194
                      195
                      196
                      197
                      198
                      199
                      200
                      201
                      202
                      203
                      204
                      205
                      206
                      207
                      208
                      209
                      210
                      211
                      212
                      213
                      214
                      215
                      216
                      217
                      218
                      219
                      220
                      221
                      222
                      223
                      224
                      225
                      226
                      227
                      228
                      229
                      230
                      231
                      232
                      233
                      234
                      235
                      236
                      237
                      238
                      239
                      240
                      241
                      242
                      243
                      244
                      245
                      246
                      247
                      248
                      249
                      250
                      251
                      252
                      253
                      254
                      255
                      256
                      257
                      258
                      259
                      260
                      261
                      262
                      263
                      264
                      265
                      266
                      267
                      268
                      269
                      270
                      271
                      272
                      273
                      274
                      275
                      276
                      277
                      278
                      279
                      280
                      281
                      282
                      283
                      284
                      285
                      286
                      287
                      288
                      289
                      290
                      291
                      292
                      293
                      294
                      295
                      296
                      297
                      298
                      299
                      300
                      301
                      302
                      303
                      304
                      305
                      306
                      307
                      308
                      309
                      310
                      311
                      312
                      313
                      314
                      315
                      316
                      317
                      318
                      319
                      320
                      321
                      322
                      323
                      324
                      325
                      326
                      327
                      328
                      329
                      330
                      331
                      332
                      333
                      334
                      335
                      336
                      337
                      338
                      339
                      340
                      341
                      342
                      343
                      344
                      345
                      346
                      347
                      348
                      349
                      350
                      351
                      352
                      353
                      354
                      355
                      356
                      357
                      358
                      359
                      360
                      361
                      362
                      363
                      364
                      365
                      366
                      367
                      368
                      369
                      370
                      371
                      372
                      373
                      374
                      375
                      376
                      377
                      378
                      379
                      380
                      381
                      382
                      383
                      class AgentsManifest(ConfigModel):
                          """Complete agent configuration manifest defining all available agents.
                      
                          This is the root configuration that:
                          - Defines available response types (both inline and imported)
                          - Configures all agent instances and their settings
                          - Sets up custom role definitions and capabilities
                          - Manages environment configurations
                      
                          A single manifest can define multiple agents that can work independently
                          or collaborate through the orchestrator.
                          """
                      
                          INHERIT: str | list[str] | None = None
                          """Inheritance references."""
                      
                          agents: dict[str, AgentConfig] = Field(default_factory=dict)
                          """Mapping of agent IDs to their configurations"""
                      
                          teams: dict[str, TeamConfig] = Field(default_factory=dict)
                          """Mapping of team IDs to their configurations"""
                      
                          storage: StorageConfig = Field(default_factory=StorageConfig)
                          """Storage provider configuration."""
                      
                          observability: ObservabilityConfig = Field(default_factory=ObservabilityConfig)
                          """Observability provider configuration."""
                      
                          conversion: ConversionConfig = Field(default_factory=ConversionConfig)
                          """Document conversion configuration."""
                      
                          responses: dict[str, ResponseDefinition] = Field(default_factory=dict)
                          """Mapping of response names to their definitions"""
                      
                          jobs: dict[str, Job] = Field(default_factory=dict)
                          """Pre-defined jobs, ready to be used by nodes."""
                      
                          mcp_servers: list[str | MCPServerConfig] = Field(default_factory=list)
                          """List of MCP server configurations:
                      
                          These MCP servers are used to provide tools and other resources to the nodes.
                          """
                          pool_server: PoolServerConfig = Field(default_factory=PoolServerConfig)
                          """Pool server configuration.
                      
                          This MCP server configuration is used for the pool MCP server,
                          which exposes pool functionality to other applications / clients."""
                      
                          prompts: PromptConfig = Field(default_factory=PromptConfig)
                      
                          model_config = ConfigDict(use_attribute_docstrings=True, extra="forbid")
                      
                          def clone_agent_config(
                              self,
                              name: str,
                              new_name: str | None = None,
                              *,
                              template_context: dict[str, Any] | None = None,
                              **overrides: Any,
                          ) -> str:
                              """Create a copy of an agent configuration.
                      
                              Args:
                                  name: Name of agent to clone
                                  new_name: Optional new name (auto-generated if None)
                                  template_context: Variables for template rendering
                                  **overrides: Configuration overrides for the clone
                      
                              Returns:
                                  Name of the new agent
                      
                              Raises:
                                  KeyError: If original agent not found
                                  ValueError: If new name already exists or if overrides invalid
                              """
                              if name not in self.agents:
                                  msg = f"Agent {name} not found"
                                  raise KeyError(msg)
                      
                              actual_name = new_name or f"{name}_copy_{len(self.agents)}"
                              if actual_name in self.agents:
                                  msg = f"Agent {actual_name} already exists"
                                  raise ValueError(msg)
                      
                              # Deep copy the configuration
                              config = self.agents[name].model_copy(deep=True)
                      
                              # Apply overrides
                              for key, value in overrides.items():
                                  if not hasattr(config, key):
                                      msg = f"Invalid override: {key}"
                                      raise ValueError(msg)
                                  setattr(config, key, value)
                      
                              # Handle template rendering if context provided
                              if template_context:
                                  # Apply name from context if not explicitly overridden
                                  if "name" in template_context and "name" not in overrides:
                                      config.name = template_context["name"]
                      
                                  # Render system prompts
                                  config.system_prompts = config.render_system_prompts(template_context)
                      
                              self.agents[actual_name] = config
                              return actual_name
                      
                          @model_validator(mode="before")
                          @classmethod
                          def resolve_inheritance(cls, data: dict) -> dict:
                              """Resolve agent inheritance chains."""
                              nodes = data.get("agents", {})
                              resolved: dict[str, dict] = {}
                              seen: set[str] = set()
                      
                              def resolve_node(name: str) -> dict:
                                  if name in resolved:
                                      return resolved[name]
                      
                                  if name in seen:
                                      msg = f"Circular inheritance detected: {name}"
                                      raise ValueError(msg)
                      
                                  seen.add(name)
                                  config = (
                                      nodes[name].model_copy()
                                      if hasattr(nodes[name], "model_copy")
                                      else nodes[name].copy()
                                  )
                                  inherit = (
                                      config.get("inherits") if isinstance(config, dict) else config.inherits
                                  )
                                  if inherit:
                                      if inherit not in nodes:
                                          msg = f"Parent agent {inherit} not found"
                                          raise ValueError(msg)
                      
                                      # Get resolved parent config
                                      parent = resolve_node(inherit)
                                      # Merge parent with child (child overrides parent)
                                      merged = parent.copy()
                                      merged.update(config)
                                      config = merged
                      
                                  seen.remove(name)
                                  resolved[name] = config
                                  return config
                      
                              # Resolve all nodes
                              for name in nodes:
                                  resolved[name] = resolve_node(name)
                      
                              # Update nodes with resolved configs
                              data["agents"] = resolved
                              return data
                      
                          @model_validator(mode="after")
                          def set_instrument_libraries(self) -> Self:
                              """Auto-set libraries to instrument based on used providers."""
                              if (
                                  not self.observability.enabled
                                  or self.observability.instrument_libraries is not None
                              ):
                                  return self
                              self.observability.instrument_libraries = list(self.get_used_providers())
                              return self
                      
                          @property
                          def node_names(self) -> list[str]:
                              """Get list of all agent and team names."""
                              return list(self.agents.keys()) + list(self.teams.keys())
                      
                          @property
                          def nodes(self) -> dict[str, Any]:
                              """Get all agent and team configurations."""
                              return {**self.agents, **self.teams}
                      
                          def get_mcp_servers(self) -> list[MCPServerConfig]:
                              """Get processed MCP server configurations.
                      
                              Converts string entries to StdioMCPServer configs by splitting
                              into command and arguments.
                      
                              Returns:
                                  List of MCPServerConfig instances
                      
                              Raises:
                                  ValueError: If string entry is empty
                              """
                              configs: list[MCPServerConfig] = []
                      
                              for server in self.mcp_servers:
                                  match server:
                                      case str():
                                          parts = server.split()
                                          if not parts:
                                              msg = "Empty MCP server command"
                                              raise ValueError(msg)
                      
                                          configs.append(StdioMCPServer(command=parts[0], args=parts[1:]))
                                      case MCPServerBase():
                                          configs.append(server)
                      
                              return configs
                      
                          @cached_property
                          def prompt_manager(self) -> PromptManager:
                              """Get prompt manager for this manifest."""
                              from llmling_agent.prompts.manager import PromptManager
                      
                              return PromptManager(self.prompts)
                      
                          # @model_validator(mode="after")
                          # def validate_response_types(self) -> AgentsManifest:
                          #     """Ensure all agent result_types exist in responses or are inline."""
                          #     for agent_id, agent in self.agents.items():
                          #         if (
                          #             isinstance(agent.result_type, str)
                          #             and agent.result_type not in self.responses
                          #         ):
                          #             msg = f"'{agent.result_type=}' for '{agent_id=}' not found in responses"
                          #             raise ValueError(msg)
                          #     return self
                      
                          def get_agent[TAgentDeps](
                              self, name: str, deps: TAgentDeps | None = None
                          ) -> AnyAgent[TAgentDeps, Any]:
                              from llmling import RuntimeConfig
                      
                              from llmling_agent import Agent, AgentContext
                      
                              config = self.agents[name]
                              # Create runtime without async context
                              cfg = config.get_config()
                              runtime = RuntimeConfig.from_config(cfg)
                      
                              # Create context with config path and capabilities
                              context = AgentContext[TAgentDeps](
                                  node_name=name,
                                  data=deps,
                                  capabilities=config.capabilities,
                                  definition=self,
                                  config=config,
                                  runtime=runtime,
                                  # pool=self,
                                  # confirmation_callback=confirmation_callback,
                              )
                      
                              sys_prompts = config.system_prompts.copy()
                              # Library prompts
                              if config.library_system_prompts:
                                  for prompt_ref in config.library_system_prompts:
                                      try:
                                          content = self.prompt_manager.get_sync(prompt_ref)
                                          sys_prompts.append(content)
                                      except Exception as e:
                                          msg = f"Failed to load library prompt {prompt_ref!r} for agent {name}"
                                          logger.exception(msg)
                                          raise ValueError(msg) from e
                              # Create agent with runtime and context
                              agent = Agent[Any](
                                  runtime=runtime,
                                  context=context,
                                  provider=config.get_provider(),
                                  system_prompt=sys_prompts,
                                  name=name,
                                  description=config.description,
                                  retries=config.retries,
                                  session=config.get_session_config(),
                                  result_retries=config.result_retries,
                                  end_strategy=config.end_strategy,
                                  capabilities=config.capabilities,
                                  debug=config.debug,
                                  # name=config.name or name,
                              )
                              if result_type := self.get_result_type(name):
                                  return agent.to_structured(result_type)
                              return agent
                      
                          def get_used_providers(self) -> set[str]:
                              """Get all providers configured in this manifest."""
                              providers = set[str]()
                      
                              for agent_config in self.agents.values():
                                  match agent_config.provider:
                                      case "pydantic_ai":
                                          providers.add("pydantic_ai")
                                      case "litellm":
                                          providers.add("litellm")
                                      case BaseProviderConfig():
                                          providers.add(agent_config.provider.type)
                              return providers
                      
                          @classmethod
                          def from_file(cls, path: StrPath) -> Self:
                              """Load agent configuration from YAML file.
                      
                              Args:
                                  path: Path to the configuration file
                      
                              Returns:
                                  Loaded agent definition
                      
                              Raises:
                                  ValueError: If loading fails
                              """
                              import yamling
                      
                              try:
                                  data = yamling.load_yaml_file(path, resolve_inherit=True)
                                  agent_def = cls.model_validate(data)
                                  # Update all agents with the config file path and ensure names
                                  agents = {
                                      name: config.model_copy(update={"config_file_path": str(path)})
                                      for name, config in agent_def.agents.items()
                                  }
                                  return agent_def.model_copy(update={"agents": agents})
                              except Exception as exc:
                                  msg = f"Failed to load agent config from {path}"
                                  raise ValueError(msg) from exc
                      
                          @cached_property
                          def pool(self) -> AgentPool:
                              """Create an agent pool from this manifest.
                      
                              Returns:
                                  Configured agent pool
                              """
                              from llmling_agent.delegation import AgentPool
                      
                              return AgentPool(manifest=self)
                      
                          def get_result_type(self, agent_name: str) -> type[Any] | None:
                              """Get the resolved result type for an agent.
                      
                              Returns None if no result type is configured.
                              """
                              agent_config = self.agents[agent_name]
                              if not agent_config.result_type:
                                  return None
                              logger.debug("Building response model for %r", agent_config.result_type)
                              if isinstance(agent_config.result_type, str):
                                  response_def = self.responses[agent_config.result_type]
                                  return response_def.create_model()  # type: ignore
                              return agent_config.result_type.create_model()  # type: ignore
                      

                      INHERIT class-attribute instance-attribute

                      INHERIT: str | list[str] | None = None
                      

                      Inheritance references.

                      agents class-attribute instance-attribute

                      agents: dict[str, AgentConfig] = Field(default_factory=dict)
                      

                      Mapping of agent IDs to their configurations

                      conversion class-attribute instance-attribute

                      conversion: ConversionConfig = Field(default_factory=ConversionConfig)
                      

                      Document conversion configuration.

                      jobs class-attribute instance-attribute

                      jobs: dict[str, Job] = Field(default_factory=dict)
                      

                      Pre-defined jobs, ready to be used by nodes.

                      mcp_servers class-attribute instance-attribute

                      mcp_servers: list[str | MCPServerConfig] = Field(default_factory=list)
                      

                      List of MCP server configurations:

                      These MCP servers are used to provide tools and other resources to the nodes.

                      node_names property

                      node_names: list[str]
                      

                      Get list of all agent and team names.

                      nodes property

                      nodes: dict[str, Any]
                      

                      Get all agent and team configurations.

                      observability class-attribute instance-attribute

                      observability: ObservabilityConfig = Field(default_factory=ObservabilityConfig)
                      

                      Observability provider configuration.

                      pool cached property

                      pool: AgentPool
                      

                      Create an agent pool from this manifest.

                      Returns:

                      Type Description
                      AgentPool

                      Configured agent pool

                      pool_server class-attribute instance-attribute

                      pool_server: PoolServerConfig = Field(default_factory=PoolServerConfig)
                      

                      Pool server configuration.

                      This MCP server configuration is used for the pool MCP server, which exposes pool functionality to other applications / clients.

                      prompt_manager cached property

                      prompt_manager: PromptManager
                      

                      Get prompt manager for this manifest.

                      responses class-attribute instance-attribute

                      responses: dict[str, ResponseDefinition] = Field(default_factory=dict)
                      

                      Mapping of response names to their definitions

                      storage class-attribute instance-attribute

                      storage: StorageConfig = Field(default_factory=StorageConfig)
                      

                      Storage provider configuration.

                      teams class-attribute instance-attribute

                      teams: dict[str, TeamConfig] = Field(default_factory=dict)
                      

                      Mapping of team IDs to their configurations

                      clone_agent_config

                      clone_agent_config(
                          name: str,
                          new_name: str | None = None,
                          *,
                          template_context: dict[str, Any] | None = None,
                          **overrides: Any,
                      ) -> str
                      

                      Create a copy of an agent configuration.

                      Parameters:

                      Name Type Description Default
                      name str

                      Name of agent to clone

                      required
                      new_name str | None

                      Optional new name (auto-generated if None)

                      None
                      template_context dict[str, Any] | None

                      Variables for template rendering

                      None
                      **overrides Any

                      Configuration overrides for the clone

                      {}

                      Returns:

                      Type Description
                      str

                      Name of the new agent

                      Raises:

                      Type Description
                      KeyError

                      If original agent not found

                      ValueError

                      If new name already exists or if overrides invalid

                      Source code in src/llmling_agent/models/manifest.py
                       92
                       93
                       94
                       95
                       96
                       97
                       98
                       99
                      100
                      101
                      102
                      103
                      104
                      105
                      106
                      107
                      108
                      109
                      110
                      111
                      112
                      113
                      114
                      115
                      116
                      117
                      118
                      119
                      120
                      121
                      122
                      123
                      124
                      125
                      126
                      127
                      128
                      129
                      130
                      131
                      132
                      133
                      134
                      135
                      136
                      137
                      138
                      139
                      140
                      141
                      142
                      143
                      144
                      def clone_agent_config(
                          self,
                          name: str,
                          new_name: str | None = None,
                          *,
                          template_context: dict[str, Any] | None = None,
                          **overrides: Any,
                      ) -> str:
                          """Create a copy of an agent configuration.
                      
                          Args:
                              name: Name of agent to clone
                              new_name: Optional new name (auto-generated if None)
                              template_context: Variables for template rendering
                              **overrides: Configuration overrides for the clone
                      
                          Returns:
                              Name of the new agent
                      
                          Raises:
                              KeyError: If original agent not found
                              ValueError: If new name already exists or if overrides invalid
                          """
                          if name not in self.agents:
                              msg = f"Agent {name} not found"
                              raise KeyError(msg)
                      
                          actual_name = new_name or f"{name}_copy_{len(self.agents)}"
                          if actual_name in self.agents:
                              msg = f"Agent {actual_name} already exists"
                              raise ValueError(msg)
                      
                          # Deep copy the configuration
                          config = self.agents[name].model_copy(deep=True)
                      
                          # Apply overrides
                          for key, value in overrides.items():
                              if not hasattr(config, key):
                                  msg = f"Invalid override: {key}"
                                  raise ValueError(msg)
                              setattr(config, key, value)
                      
                          # Handle template rendering if context provided
                          if template_context:
                              # Apply name from context if not explicitly overridden
                              if "name" in template_context and "name" not in overrides:
                                  config.name = template_context["name"]
                      
                              # Render system prompts
                              config.system_prompts = config.render_system_prompts(template_context)
                      
                          self.agents[actual_name] = config
                          return actual_name
                      

                      from_file classmethod

                      from_file(path: StrPath) -> Self
                      

                      Load agent configuration from YAML file.

                      Parameters:

                      Name Type Description Default
                      path StrPath

                      Path to the configuration file

                      required

                      Returns:

                      Type Description
                      Self

                      Loaded agent definition

                      Raises:

                      Type Description
                      ValueError

                      If loading fails

                      Source code in src/llmling_agent/models/manifest.py
                      332
                      333
                      334
                      335
                      336
                      337
                      338
                      339
                      340
                      341
                      342
                      343
                      344
                      345
                      346
                      347
                      348
                      349
                      350
                      351
                      352
                      353
                      354
                      355
                      356
                      357
                      358
                      @classmethod
                      def from_file(cls, path: StrPath) -> Self:
                          """Load agent configuration from YAML file.
                      
                          Args:
                              path: Path to the configuration file
                      
                          Returns:
                              Loaded agent definition
                      
                          Raises:
                              ValueError: If loading fails
                          """
                          import yamling
                      
                          try:
                              data = yamling.load_yaml_file(path, resolve_inherit=True)
                              agent_def = cls.model_validate(data)
                              # Update all agents with the config file path and ensure names
                              agents = {
                                  name: config.model_copy(update={"config_file_path": str(path)})
                                  for name, config in agent_def.agents.items()
                              }
                              return agent_def.model_copy(update={"agents": agents})
                          except Exception as exc:
                              msg = f"Failed to load agent config from {path}"
                              raise ValueError(msg) from exc
                      

                      get_mcp_servers

                      get_mcp_servers() -> list[MCPServerConfig]
                      

                      Get processed MCP server configurations.

                      Converts string entries to StdioMCPServer configs by splitting into command and arguments.

                      Returns:

                      Type Description
                      list[MCPServerConfig]

                      List of MCPServerConfig instances

                      Raises:

                      Type Description
                      ValueError

                      If string entry is empty

                      Source code in src/llmling_agent/models/manifest.py
                      216
                      217
                      218
                      219
                      220
                      221
                      222
                      223
                      224
                      225
                      226
                      227
                      228
                      229
                      230
                      231
                      232
                      233
                      234
                      235
                      236
                      237
                      238
                      239
                      240
                      241
                      242
                      def get_mcp_servers(self) -> list[MCPServerConfig]:
                          """Get processed MCP server configurations.
                      
                          Converts string entries to StdioMCPServer configs by splitting
                          into command and arguments.
                      
                          Returns:
                              List of MCPServerConfig instances
                      
                          Raises:
                              ValueError: If string entry is empty
                          """
                          configs: list[MCPServerConfig] = []
                      
                          for server in self.mcp_servers:
                              match server:
                                  case str():
                                      parts = server.split()
                                      if not parts:
                                          msg = "Empty MCP server command"
                                          raise ValueError(msg)
                      
                                      configs.append(StdioMCPServer(command=parts[0], args=parts[1:]))
                                  case MCPServerBase():
                                      configs.append(server)
                      
                          return configs
                      

                      get_result_type

                      get_result_type(agent_name: str) -> type[Any] | None
                      

                      Get the resolved result type for an agent.

                      Returns None if no result type is configured.

                      Source code in src/llmling_agent/models/manifest.py
                      371
                      372
                      373
                      374
                      375
                      376
                      377
                      378
                      379
                      380
                      381
                      382
                      383
                      def get_result_type(self, agent_name: str) -> type[Any] | None:
                          """Get the resolved result type for an agent.
                      
                          Returns None if no result type is configured.
                          """
                          agent_config = self.agents[agent_name]
                          if not agent_config.result_type:
                              return None
                          logger.debug("Building response model for %r", agent_config.result_type)
                          if isinstance(agent_config.result_type, str):
                              response_def = self.responses[agent_config.result_type]
                              return response_def.create_model()  # type: ignore
                          return agent_config.result_type.create_model()  # type: ignore
                      

                      get_used_providers

                      get_used_providers() -> set[str]
                      

                      Get all providers configured in this manifest.

                      Source code in src/llmling_agent/models/manifest.py
                      318
                      319
                      320
                      321
                      322
                      323
                      324
                      325
                      326
                      327
                      328
                      329
                      330
                      def get_used_providers(self) -> set[str]:
                          """Get all providers configured in this manifest."""
                          providers = set[str]()
                      
                          for agent_config in self.agents.values():
                              match agent_config.provider:
                                  case "pydantic_ai":
                                      providers.add("pydantic_ai")
                                  case "litellm":
                                      providers.add("litellm")
                                  case BaseProviderConfig():
                                      providers.add(agent_config.provider.type)
                          return providers
                      

                      resolve_inheritance classmethod

                      resolve_inheritance(data: dict) -> dict
                      

                      Resolve agent inheritance chains.

                      Source code in src/llmling_agent/models/manifest.py
                      146
                      147
                      148
                      149
                      150
                      151
                      152
                      153
                      154
                      155
                      156
                      157
                      158
                      159
                      160
                      161
                      162
                      163
                      164
                      165
                      166
                      167
                      168
                      169
                      170
                      171
                      172
                      173
                      174
                      175
                      176
                      177
                      178
                      179
                      180
                      181
                      182
                      183
                      184
                      185
                      186
                      187
                      188
                      189
                      190
                      191
                      192
                      193
                      @model_validator(mode="before")
                      @classmethod
                      def resolve_inheritance(cls, data: dict) -> dict:
                          """Resolve agent inheritance chains."""
                          nodes = data.get("agents", {})
                          resolved: dict[str, dict] = {}
                          seen: set[str] = set()
                      
                          def resolve_node(name: str) -> dict:
                              if name in resolved:
                                  return resolved[name]
                      
                              if name in seen:
                                  msg = f"Circular inheritance detected: {name}"
                                  raise ValueError(msg)
                      
                              seen.add(name)
                              config = (
                                  nodes[name].model_copy()
                                  if hasattr(nodes[name], "model_copy")
                                  else nodes[name].copy()
                              )
                              inherit = (
                                  config.get("inherits") if isinstance(config, dict) else config.inherits
                              )
                              if inherit:
                                  if inherit not in nodes:
                                      msg = f"Parent agent {inherit} not found"
                                      raise ValueError(msg)
                      
                                  # Get resolved parent config
                                  parent = resolve_node(inherit)
                                  # Merge parent with child (child overrides parent)
                                  merged = parent.copy()
                                  merged.update(config)
                                  config = merged
                      
                              seen.remove(name)
                              resolved[name] = config
                              return config
                      
                          # Resolve all nodes
                          for name in nodes:
                              resolved[name] = resolve_node(name)
                      
                          # Update nodes with resolved configs
                          data["agents"] = resolved
                          return data
                      

                      set_instrument_libraries

                      set_instrument_libraries() -> Self
                      

                      Auto-set libraries to instrument based on used providers.

                      Source code in src/llmling_agent/models/manifest.py
                      195
                      196
                      197
                      198
                      199
                      200
                      201
                      202
                      203
                      204
                      @model_validator(mode="after")
                      def set_instrument_libraries(self) -> Self:
                          """Auto-set libraries to instrument based on used providers."""
                          if (
                              not self.observability.enabled
                              or self.observability.instrument_libraries is not None
                          ):
                              return self
                          self.observability.instrument_libraries = list(self.get_used_providers())
                          return self