Skip to main content
Packaging a service means creating the configuration files that tell MeshAgent how to run your code. MeshAgent can run your code as a Project Service (available in every room) or a Room Service (scoped to a specific room). For containerized services, you’ll create a YAML configuration file and a Dockerfile. For external services, you just need a YAML configuration file with a URL pointing to where your service is already running. Services can be configured via MeshAgent Studio or using a meshagent.yaml configuration file. In this document we’ll walk through how to decide which configuration type to use (Service or ServiceTemplate), create your YAML configuration file, and build a Dockerfile for containerized services. Then we’ll be ready to deploy the service and explore end to end examples. ​

Defining the Service

You’ll write one of two types of configuration files depending on whether the service requires configuration at runtime:
  • ServiceSpec (kind: Service): A concrete spec of what runs. Use it when configuration is fixed and does not need user input. This is useful when deploying via CI/CD.
  • ServiceTemplateSpec (kind: ServiceTemplate): A parameterized template that collects runtime inputs and renders a ServiceSpec. Use it when you’re packaging a service for others to customize. For example, if users need to supply their own API keys, prompts, or other settings.

Key Differences

A ServiceSpec maps directly to what will run. A ServiceTemplateSpec needs configuration first — when you provide values for its variables, MeshAgent calls to_service_spec() to generate the actual ServiceSpec that runs. Both can be used for project services or room services. The choice depends on whether you need runtime configuration, not on the deployment scope.

Configuration Overview

FieldRequiredUsed ByDescription
versionYesBothAlways “v1”
kindYesBoth”Service” or “ServiceTemplate”
metadataYesBothService identity and display information
agentsNoBothRegister the agent identities exposed by the service
portsNoBothEndpoints MeshAgent can call
container*BothContainer configuration (mutually exclusive with external)
external*BothExternal service URL (mutually exclusive with container)
variablesNoServiceTemplate onlyUser inputs for templating (used with container services only)
* Either container or external is required, but not both.

Field Reference

Metadata

The metadata section identifies your service and provides information displayed in the UI.
FieldTypeRequiredDescription
namestringYesUnique service name
descriptionstringNoDescription shown in UI
repostringNoSource code repository URL
iconstringNoIcon/emoji for UI display
annotationsobjectNoCustom key-value metadata
Example Syntax:
yaml
metadata:
  name: my-service             # Required: Unique service name
  description: "A sample agent service"  # Optional: Description shown in UI
  repo: "https://..."          # Optional: Source code repository
  icon: "🤖"                   # Optional: Icon for UI
  annotations:                 # Optional: Custom key-value metadata, could also be links to external paths
    team: "platform"

Agents

Use the agents list to declare the MeshAgent identities your service provides. This helps MeshAgent route requests, apply agent-specific policies, and present the right agents in the UI.
FieldTypeRequiredDescription
namestringYesUnique agent identity within the service
descriptionstringNoDisplay text describing the agent
annotationsobjectNoKey-value metadata about the agent (for example meshagent.agent.type)
Example Syntax:
yaml
agents:
  - name: assistant
    description: "Conversational agent for the room"
    annotations:
      meshagent.agent.type: "ChatBot"

Ports

Define how MeshAgent connects to your service. Each port can expose multiple endpoints.
FieldTypeRequiredDescription
num"*" or intYesPort number or "*" for auto-assignment
typestringNoProtocol type: http or tcp
livenessstringNoPath for health checks
endpointslistNoList of endpoints this port serves
Example Syntax:
yaml
ports:
  - num: "*"               # Port number or "*" for auto-assignment
    type: http             # Optional: http or tcp
    liveness: "/"          # Optional: Health check path
    endpoints:             # Each endpoint must specify a path and either meshagent or mcp configuration
      - path: /agent
        meshagent:
          identity: my-agent

Endpoints

Each endpoint must specify a path and either meshagent or mcp configuration. MeshAgent Endpoints For MeshAgent native services built with ServiceHost.
FieldTypeRequiredDescription
identitystringYesUnique identity for the service in the room
apiobjectNoAPI scope overrides (see API Scopes)
Example MeshAgent Endpoint Syntax:
yaml
endpoints:
  - path: /agent
    meshagent:              # For MeshAgent-native services
      identity: my-agent    # Required: Identity for the service
      api:                  # Optional: API scope overrides
        queues:
          send: ["notifications"]
        storage:
          paths:
            - path: "/data"
              read_only: true
MCP Endpoints For Model Context Protocol (MCP) servers
FieldTypeRequiredDescription
labelstringYesDisplay name for the MCP server
descriptionstringYesDescription of what the server provides
allowed_toolslistNoFilter which tools are available. Includes list of tools and weather they are read_only
headersobjectNoCustom headers to include
require_approvalstringNo”always” or “never”
oauthobjectNoOAuth configuration
openai_connector_idstringNoOpenAI connector ID
OAuth Configuration with MCP The oauth field allows you to define an oauth configuration for the MCP server.
FieldTypeRequiredDescription
client_idstringYesOAuth client ID
client_secretstringNoOAuth client secret
authorization_endpointstringYesOAuth authorization endpoint URL
token_endpointstringYesOAuth token endpoint URL
no_pkcebooleanNoWhether to disable PKCE (Proof Key for Code Exchange)
scopeslistNoList of OAuth scopes to request
Example MCP Endpoint Syntax:
yaml
endpoints:
  - path: /mcp
    mcp:
      label: "mcp-tools"                     # Required: Display name
      description: "MCP Tools"               # Required: Description
      allowed_tools:                         # Optional: Filter which tools are available
        - tool_names: ["tool_1", "tool_2"]
          read_only: false
      headers:                               # Optional: Custom headers
        custom-header: value
      require_approval: "never"              # Optional: "always" or "never"
      oauth:                                 # Optional: OAuth configuration
        client_id: "..."
        client_secret: "..."
        authorization_endpoint: "https://..."
        token_endpoint: "https://..."
        no_pkce: false                       # Optional: depends on if pkce is used
        scopes: ["scope1", "scope2"]
      openai_connector_id: "..."             # Optional: OpenAI connector ID

External

Use external when your service is already running elsewhere. MeshAgent will route calls to the URL you provide.
yaml
external:
  url: "https://api.example.com"  # Required: URL where service is running

Container

Use container when MeshAgent should run your service in a container. Containers can be used with both ServiceSpec and ServiceTemplateSpec. However, only containers started by the room as a service can use secrets, this is to prevent a user from being able to dynamically pull private images in registries they don’t have access to.
FieldTypeRequiredDescription
imagestringYesContainer image (e.g., registry/image:tag)
commandstringNoOverride container entrypoint
environmentlistNoEnvironment variables
secretslistNoSecret IDs to inject as environment variables (ServiceSpec only)
pull_secretstringNoSecret ID for accessing private registries (ServiceSpec only)
storageobjectNoMount room or project storage
api_keyobjectNoAuto-provision API key for the service (ServiceSpec only)

Storage

Use the storage field to mount room or project storage into your container.
  • Room storage: Per-room files, read/write by default
  • Project storage: Shared across all rooms, read-only by default
FieldTypeRequiredDescription
pathstringYesMount path inside the container
subpathstringNoSubdirectory within the storage volume
read_onlybooleanNoWhether the mount is read-only

API Key Provisioning

The api_key field allows your container service to request an admin API key be automatically provisioned and injected. This is useful when your service needs to call MeshAgent APIs directly (e.g., to manage participants, create resources, etc.).
FieldTypeRequiredDescription
rolestringYesAlways “admin”
namestringYesName for the API key
auto_provisionbooleanNoAuto-provision on deployment
Container Example Syntax:
yaml
container:
  image: registry/image:tag             # Required: Container image
  command: "python main.py"             # Optional: Override entrypoint
  environment:                          # Optional: Environment variables
    - name: VAR_NAME
      value: "{var_name}"
  secrets: ["secret-id"]                # Optional: Secret IDs to inject
  pull_secret: "image-pull-secret-id"   # Optional: Secret ID for private registries
  storage:                              # Optional: Mount storage
    room:
      - path: /data
        subpath: "uploads"
        read_only: false
    project:
      - path: /shared
        read_only: true
  api_key:                              # Optional: Auto-provision API key for service
    role: "admin"                       # Required: Role for the API key (always admin)
    name: "name"                        # Required: Name for the API key
    auto_provision: true                # Optional: Auto-provision on deployment (default: True)

Variables (only for ServiceTemplate)

Variables define what values users can provide when a container-based service launches. You can restrict inputs or hide sensitive ones. Variables from the ServiceTemplate will be mapped to environment variables in the container.
FieldTypeRequiredDescription
namestringYesVariable identifier used in {variable_name} substitution
descriptionstringNoHelp text shown in the UI
enumlistNoRestrict to specific values (dropdown displayed in UI)
optionalbooleanNoWhether the variable is required
obscurebooleanNoHide the value in the UI (for sensitive data)
typestringNoType hint (e.g., email). Set to email if creating an email address
For example, if you need to pass a system prompt or api key you can setup the variables section like this:
yaml
variables:
- name: "system_prompt"
  description: "The system prompt for the chatbot"
- name: "tone"
  description: "Tone of the model"
  enum: ["formal", "casual", "enthusiastic"]
  optional: true
- name: "api_key"
  description: "External API key"
  obscure: true  # Hide value in UI
Mapping Variables to Environment Variables Use syntax in the environment section of your container definition to map user-provided values to environment variables. For example:
environment:
- name: SYSTEM_PROMPT
  value: "{system_prompt}"
- name: TONE
  value: "{tone}"
- name: OPENAI_API_KEY
  value: "{api_key}"

Creating a Dockerfile for your Service

If you’re using a container for your service, you will need to create a Dockerfile that installs all the libraries required to run your service. You can use MeshAgent provided base images as a starting point. These images install the MeshAgent packages automatically. For example:
Dockerfile
FROM meshagent/python-sdk-slim:latest

COPY . /src
WORKDIR /src

ENTRYPOINT [ "python3", "main.py" ]

Next Steps