Skip to content

manifest

Class info

Classes

Name Children Inherits
AgentConfig
llmling_agent.models.agents
Configuration for a single agent in the system.
    • NodeConfig
    AgentWorkerConfig
    llmling_agent_config.workers
    Configuration for agent workers.
      • BaseWorkerConfig
      AgentsManifest
      llmling_agent.models.manifest
      Complete agent configuration manifest defining all available agents.
        BaseMCPServerConfig
        llmling_agent_config.mcp_server
        Base model for MCP server configuration.
        • StdioMCPServerConfig
        • SSEMCPServerConfig
        • StreamableHTTPMCPServerConfig
        BaseProviderConfig
        llmling_agent_config.providers
        Base configuration for agent providers.
        • PydanticAIProviderConfig
        • LiteLLMProviderConfig
        • HumanProviderConfig
        • CallbackProviderConfig
        BaseWorkerConfig
        llmling_agent_config.workers
        Base configuration for workers.
        • TeamWorkerConfig
        • AgentWorkerConfig
        ConversionConfig
        llmling_agent_config.converters
        Global conversion configuration.
          Job
          llmling_agent_config.task
          A task is a piece of work that can be executed by an agent.
            ObservabilityConfig
            llmling_agent_config.observability
            Global observability configuration.
              PoolServerConfig
              llmling_agent_config.mcp_server
              Configuration for pool-based MCP server.
                PromptConfig
                llmling_agent_config.prompts
                Complete prompt configuration.
                  ResourceRegistry
                  llmling_agent.resource_registry
                  Registry for filesystem resources.
                    SourceResourceConfig
                    llmling_agent_config.resources
                    Configuration for a single filesystem source.
                      • BaseResourceConfig
                      StdioMCPServerConfig
                      llmling_agent_config.mcp_server
                      MCP server started via stdio.
                        • BaseMCPServerConfig
                        StdlibUIConfig
                        llmling_agent_config.ui
                        Configuration for basic CLI interface.
                          • BaseUIConfig
                          StorageConfig
                          llmling_agent_config.storage
                          Global storage configuration.
                            StructuredResponseConfig
                            llmling_agent_config.result_types
                            Base class for response definitions.
                              TeamConfig
                              llmling_agent_config.teams
                              Configuration for a team or chain of message nodes.
                                • NodeConfig
                                TeamWorkerConfig
                                llmling_agent_config.workers
                                Configuration for team workers.
                                  • BaseWorkerConfig

                                  🛈 DocStrings

                                  Models for agent configuration.

                                  AgentsManifest

                                  Bases: Schema

                                  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
                                   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
                                  384
                                  385
                                  386
                                  387
                                  388
                                  389
                                  390
                                  391
                                  392
                                  393
                                  394
                                  395
                                  396
                                  397
                                  398
                                  399
                                  400
                                  401
                                  402
                                  403
                                  404
                                  405
                                  406
                                  407
                                  408
                                  409
                                  410
                                  411
                                  412
                                  413
                                  414
                                  415
                                  416
                                  417
                                  418
                                  419
                                  420
                                  421
                                  422
                                  423
                                  424
                                  425
                                  426
                                  427
                                  428
                                  429
                                  430
                                  431
                                  432
                                  433
                                  434
                                  435
                                  436
                                  437
                                  438
                                  439
                                  440
                                  441
                                  442
                                  443
                                  444
                                  445
                                  446
                                  447
                                  448
                                  449
                                  450
                                  451
                                  452
                                  453
                                  454
                                  455
                                  456
                                  457
                                  458
                                  459
                                  460
                                  461
                                  462
                                  463
                                  464
                                  465
                                  466
                                  467
                                  468
                                  469
                                  470
                                  471
                                  472
                                  473
                                  474
                                  475
                                  476
                                  477
                                  478
                                  479
                                  480
                                  481
                                  482
                                  483
                                  484
                                  485
                                  class AgentsManifest(Schema):
                                      """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."""
                                  
                                      resources: dict[str, ResourceConfig | str] = Field(default_factory=dict)
                                      """Resource configurations defining available filesystems.
                                  
                                      Supports both full config and URI shorthand:
                                          resources:
                                            docs: "file://./docs"  # shorthand
                                            data:  # full config
                                              type: "source"
                                              uri: "s3://bucket/data"
                                              cached: true
                                      """
                                  
                                      ui: UIConfig = Field(default_factory=StdlibUIConfig)
                                      """UI configuration."""
                                  
                                      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, StructuredResponseConfig] = 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")
                                  
                                      @model_validator(mode="before")
                                      @classmethod
                                      def normalize_workers(cls, data: dict[str, Any]) -> dict[str, Any]:
                                          """Convert string workers to appropriate WorkerConfig for all agents."""
                                          teams = data.get("teams", {})
                                          agents = data.get("agents", {})
                                  
                                          # Process workers for all agents that have them
                                          for agent_name, agent_config in agents.items():
                                              if isinstance(agent_config, dict):
                                                  workers = agent_config.get("workers", [])
                                              else:
                                                  workers = agent_config.workers
                                  
                                              if workers:
                                                  normalized: list[BaseWorkerConfig] = []
                                  
                                                  for worker in workers:
                                                      match worker:
                                                          case str() as name:
                                                              # Determine type based on presence in teams/agents
                                                              if name in teams:
                                                                  normalized.append(TeamWorkerConfig(name=name))
                                                              elif name in agents:
                                                                  normalized.append(AgentWorkerConfig(name=name))
                                                              else:
                                                                  # Default to agent if type can't be determined
                                                                  normalized.append(AgentWorkerConfig(name=name))
                                  
                                                          case dict() as config:
                                                              # If type is explicitly specified, use it
                                                              if worker_type := config.get("type"):
                                                                  match worker_type:
                                                                      case "team":
                                                                          normalized.append(TeamWorkerConfig(**config))
                                                                      case "agent":
                                                                          normalized.append(AgentWorkerConfig(**config))
                                                                      case _:
                                                                          msg = f"Invalid worker type: {worker_type}"
                                                                          raise ValueError(msg)
                                                              else:
                                                                  # Determine type based on worker name
                                                                  worker_name = config.get("name")
                                                                  if not worker_name:
                                                                      msg = "Worker config missing name"
                                                                      raise ValueError(msg)
                                  
                                                                  if worker_name in teams:
                                                                      normalized.append(TeamWorkerConfig(**config))
                                                                  else:
                                                                      normalized.append(AgentWorkerConfig(**config))
                                  
                                                          case BaseWorkerConfig():  # Already normalized
                                                              normalized.append(worker)
                                  
                                                          case _:
                                                              msg = f"Invalid worker configuration: {worker}"
                                                              raise ValueError(msg)
                                  
                                                  if isinstance(agent_config, dict):
                                                      agent_config["workers"] = normalized
                                                  else:
                                                      # Need to create a new dict with updated workers
                                                      agent_dict = agent_config.model_dump()
                                                      agent_dict["workers"] = normalized
                                                      agents[agent_name] = agent_dict
                                  
                                          return data
                                  
                                      @cached_property
                                      def resource_registry(self) -> ResourceRegistry:
                                          """Get registry with all configured resources."""
                                          registry = ResourceRegistry()
                                          for name, config in self.resources.items():
                                              if isinstance(config, str):
                                                  # Convert URI shorthand to SourceResourceConfig
                                                  config = SourceResourceConfig(uri=config)
                                              registry.register_from_config(name, config)
                                          return registry
                                  
                                      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 StdioMCPServerConfig 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(StdioMCPServerConfig(command=parts[0], args=parts[1:]))
                                                  case BaseMCPServerConfig():
                                                      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 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.response_schema.get_schema()  # type: ignore
                                          return agent_config.result_type.response_schema.get_schema()  # 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.

                                  resource_registry cached property

                                  resource_registry: ResourceRegistry
                                  

                                  Get registry with all configured resources.

                                  resources class-attribute instance-attribute

                                  resources: dict[str, ResourceConfig | str] = Field(default_factory=dict)
                                  

                                  Resource configurations defining available filesystems.

                                  Supports both full config and URI shorthand

                                  resources: docs: "file://./docs" # shorthand data: # full config type: "source" uri: "s3://bucket/data" cached: true

                                  responses class-attribute instance-attribute

                                  responses: dict[str, StructuredResponseConfig] = 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

                                  ui class-attribute instance-attribute

                                  ui: UIConfig = Field(default_factory=StdlibUIConfig)
                                  

                                  UI configuration.

                                  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
                                  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
                                  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
                                  434
                                  435
                                  436
                                  437
                                  438
                                  439
                                  440
                                  441
                                  442
                                  443
                                  444
                                  445
                                  446
                                  447
                                  448
                                  449
                                  450
                                  451
                                  452
                                  453
                                  454
                                  455
                                  456
                                  457
                                  458
                                  459
                                  460
                                  @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 StdioMCPServerConfig 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
                                  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
                                  def get_mcp_servers(self) -> list[MCPServerConfig]:
                                      """Get processed MCP server configurations.
                                  
                                      Converts string entries to StdioMCPServerConfig 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(StdioMCPServerConfig(command=parts[0], args=parts[1:]))
                                              case BaseMCPServerConfig():
                                                  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
                                  473
                                  474
                                  475
                                  476
                                  477
                                  478
                                  479
                                  480
                                  481
                                  482
                                  483
                                  484
                                  485
                                  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.response_schema.get_schema()  # type: ignore
                                      return agent_config.result_type.response_schema.get_schema()  # 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
                                  420
                                  421
                                  422
                                  423
                                  424
                                  425
                                  426
                                  427
                                  428
                                  429
                                  430
                                  431
                                  432
                                  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
                                  

                                  normalize_workers classmethod

                                  normalize_workers(data: dict[str, Any]) -> dict[str, Any]
                                  

                                  Convert string workers to appropriate WorkerConfig for all agents.

                                  Source code in src/llmling_agent/models/manifest.py
                                  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
                                  @model_validator(mode="before")
                                  @classmethod
                                  def normalize_workers(cls, data: dict[str, Any]) -> dict[str, Any]:
                                      """Convert string workers to appropriate WorkerConfig for all agents."""
                                      teams = data.get("teams", {})
                                      agents = data.get("agents", {})
                                  
                                      # Process workers for all agents that have them
                                      for agent_name, agent_config in agents.items():
                                          if isinstance(agent_config, dict):
                                              workers = agent_config.get("workers", [])
                                          else:
                                              workers = agent_config.workers
                                  
                                          if workers:
                                              normalized: list[BaseWorkerConfig] = []
                                  
                                              for worker in workers:
                                                  match worker:
                                                      case str() as name:
                                                          # Determine type based on presence in teams/agents
                                                          if name in teams:
                                                              normalized.append(TeamWorkerConfig(name=name))
                                                          elif name in agents:
                                                              normalized.append(AgentWorkerConfig(name=name))
                                                          else:
                                                              # Default to agent if type can't be determined
                                                              normalized.append(AgentWorkerConfig(name=name))
                                  
                                                      case dict() as config:
                                                          # If type is explicitly specified, use it
                                                          if worker_type := config.get("type"):
                                                              match worker_type:
                                                                  case "team":
                                                                      normalized.append(TeamWorkerConfig(**config))
                                                                  case "agent":
                                                                      normalized.append(AgentWorkerConfig(**config))
                                                                  case _:
                                                                      msg = f"Invalid worker type: {worker_type}"
                                                                      raise ValueError(msg)
                                                          else:
                                                              # Determine type based on worker name
                                                              worker_name = config.get("name")
                                                              if not worker_name:
                                                                  msg = "Worker config missing name"
                                                                  raise ValueError(msg)
                                  
                                                              if worker_name in teams:
                                                                  normalized.append(TeamWorkerConfig(**config))
                                                              else:
                                                                  normalized.append(AgentWorkerConfig(**config))
                                  
                                                      case BaseWorkerConfig():  # Already normalized
                                                          normalized.append(worker)
                                  
                                                      case _:
                                                          msg = f"Invalid worker configuration: {worker}"
                                                          raise ValueError(msg)
                                  
                                              if isinstance(agent_config, dict):
                                                  agent_config["workers"] = normalized
                                              else:
                                                  # Need to create a new dict with updated workers
                                                  agent_dict = agent_config.model_dump()
                                                  agent_dict["workers"] = normalized
                                                  agents[agent_name] = agent_dict
                                  
                                      return data
                                  

                                  resolve_inheritance classmethod

                                  resolve_inheritance(data: dict) -> dict
                                  

                                  Resolve agent inheritance chains.

                                  Source code in src/llmling_agent/models/manifest.py
                                  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
                                  @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
                                  297
                                  298
                                  299
                                  300
                                  301
                                  302
                                  303
                                  304
                                  305
                                  306
                                  @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