convention

module
v0.0.0-...-c9de236 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 29, 2025 License: MIT

README

Convention

Convention defines standards for building containerized, multi-tenant, multi-entity agent architectures. This document specifies the core concepts, security practices, communication protocols, and data management guidelines required to operate and integrate with Convention-compliant systems.

A reference implementation is available in ./lib supporting Go and Dart.

Glossary

  • Agent: A program with a specific purpose in the system, striving to fulfil its purpose independently of external signals.
  • Tenant: A unique identifier for a tenant supported by the system. Convention implements multitenancy by default.
  • User: A unique identifier for an authenticated user. Each agent can authenticate as a user using its name as the identifier.
  • Entity: A unique identifier for a legal entity, with each user possibly having multiple entities. Data is stored by entity to enable a user to access multiple entities (e.g., personal and business financial accounts).
  • Role: A unique string that defines a user's specific permissions within the system.
  • Permission: A unique identifier for allowed actions within the system.
  • Action: A unique identifier for an operation and resource, mapping to HTTP methods and paths, e.g., GET /message/v1/tenants/default/entities/ecf8efa3/messages/f38ce157.
  • Workflow: A unique identifier for the specific workload that is being handled by an agent.

Configuration and Secrets Management

Configuration Overview

Convention is designed for containerized environments where secrets are mounted to the container's file system.

There is no distinction between secrets and configuration values; both must follow best practices for secret management as defined by the hosting environment.

Configuration Keys/Files

By default, all configuration files are stored in /etc/agent.

The following keys/files must be automatically provided by the hosting environment:

  • environment: Specifies the environment name, with "production" as the production environment.
  • communication_certificate: SSL certificate for internal HTTPS communication.
  • communication_key: SSL key for internal HTTPS communication.
  • communication_secret: Secret used for signing and verifying authorization tokens.
  • database: Configuration details for accessing the system's database.

Communication Protocol

All communication uses the HTTP protocol with a JSON-formatted body.

Secure Communication

All communication is secured with SSL (HTTPS), using the communication_certificate and communication_key located at /etc/agent.

The communication_certificate must be trusted by the container hosting OS.

Actions and Resources

Each action includes an operation and a resource, corresponding to HTTP methods and paths. The agent name and version always appear as the first segments of a resource identifier.

In the example below, the agent name is "message-v1":

GET /message/v1/tenants/default/entities/ecf8efa3/messages/f38ce157
Error Handling

Errors are communicated in JSON format with code and message fields:

{
    "code": "...",
    "message": "..."
}
Workflow and Agent Headers

Every task engaged by an agent must have a workflow identifier. If the task is initiated by an incoming HTTP request, the agent should use the workflow identifier from the Workflow HTTP header.

If no workflow identifier is available, the agent must generate a new unique workflow identifier and pass it along.

Workflow headers should be included in all outgoing HTTP requests as well as the Agent header containing the agent name.

Example:

GET /message/v1/tenants/default/entities/ecf8efa3/messages/f38ce157
Workflow: {workflow identifier}
Agent: {agent name}
Time Management (Test Environments Only)

In non-production environments, agents must adhere to the Time-Now header from the incoming HTTP request to simulate different times. The format follows RFC3339 (e.g., 2006-01-02T15:04:05Z07:00).

The Time-Now header must be ignored in production environments.

Example:

GET /message/v1/tenants/default/entities/ecf8efa3/messages/f38ce157
Workflow: {workflow identifier}
Agent: {agent name}
Time-Now: 2024-01-02T15:04:05Z07:00

Authentication and Authorization

Authentication with JWT Tokens

Convention uses JWT tokens for internal authentication, passed in the Authorization header.

Example:

GET /message/v1/tenants/default/entities/ecf8efa3/messages/f38ce157
Workflow: {workflow identifier}
Agent: {agent name}
Authorization: Bearer {token}

Tokens are signed with the communication_secret in /etc/agent/communication_secret.

Required JWT Claims

The JWT tokens must include the following claims:

Claim Type Description
agent string Agent name
user string Authenticated user
tenants array of strings User's tenants
entities array of strings Entities accessible by the user
roles array of strings User's assigned roles
Role-Based Access Control

In addition to the user claims, all agents have access to common configuration details about:

  • roles: All known roles within the system.
    • permissions: All permissions allowed for each role.
      • action templates: All action templates allowed for each permission.

In JSON format a simple configuration can look like:

{
    "roles": {
        "user": [
            "write_tenant_messages",
            "read_own_messages"
        ],
        "admin": [
            "write_tenant_messages",
            "read_tenant_messages"
        ]
    },
    "permissions": {
        "write_tenant_messages": [
            "PUT /message/v1/tenants/{tenant}/entities/{any}/messages/{any}"
        ],
        "read_tenant_messages": [
            "GET /message/v1/tenants/{tenant}/entities/{any}/messages/{any}"
        ],
        "read_own_messages": [
            "GET /message/v1/tenants/{tenant}/entities/{entity}/messages/{any}"
        ]
    },
    "public": [
        "GET /message/v1/openapi.yaml"
    ]
}

Access control is achieved by extracting all allowed action templates from the user's roles and matching them against the incoming action (HTTP request).

For example, the action template:

GET /message/v1/tenants/{tenant}/entities/{entity}/messages/{any}

will match the action:

GET /message/v1/tenants/default/entities/ecf8efa3/messages/f38ce157

only when the authenticated user has access to the corresponding action template (through "user" role) and has a tenant and entity in their authorization claims that match the values "default" and "ecf8efa3".

Action Template Placeholders

The action template supports the following placeholders:

  • {any}: Ignore any value in this part of the path.
  • {any...}: Ignore any value from this point onward in the path.
  • {user}: Identifies the user as part of the path; a check will be performed to ensure the user matches the authenticated user.
  • {tenant}: Identifies the tenant as part of the path; a check will be performed to ensure the tenant is allowed for the authenticated user.
  • {entity}: Identifies the entity as part of the path; a check will be performed to ensure the entity is allowed for the authenticated user.

Data Storage and Sharding

Vaults

First segmentation of database in Convention is called vault. Through different vault names, Convention enables access to different databases, schemas, or database servers.

This approach is also useful to facilitate schema updates or database engine changes as part of the agent's operations.

Multitenancy

The multi-tenancy is directly implemented in the database. Each tenant has its own database connection, ensuring data isolation and security.

Sharding

Database sharding in Convention allows data to be distributed across multiple databases, schemas, or servers. This approach enhances performance and scalability by balancing the data load, ensuring that no single database becomes a bottleneck.

Each shard contains a subset of the data, and the Convention implementation should intelligently route queries to the appropriate shard based on the data's partitioning logic. Each tenant can have one or multiple shards.

Changing the number of shards requires a full data migration, which can be achieved through the multi vault mechanism. This allows each agent to migrate its own data as part of their operations.

Database Configuration

Database configurations are located in the database key in /etc/agent/database, specifying database connection per vault, tenants, and shards.

{
    "cache": {
        "tenant1": [
            {
                "engine": "sqlite",
                "in_memory": true
            }
        ]
    },
    "messages": {
        "tenant1": [
            {
                "host": "127.0.0.1",
                "port": 5432,
                "database": "t1_messages_shard1",
                "username": "some_user",
                "password": "some_password"
            },
            {
                "host": "127.0.0.1",
                "port": 5432,
                "database": "t1_messages_shard2",
                "username": "some_user",
                "password": "some_password"
            }
        ]
    }
}

Logging and Monitoring

Logging Structure

Logs in Convention are collected from stdout in JSON format, each entry ending with a newline (\n).

Log Messages

There are four log levels for messages: "error", "warning", "info", and "debug".

Logs are formatted as follows:

{
    "time": "2023-10-01T01:00:00Z",
    "level": "error",
    "agent": "message-v1",
    "user": "josh",
    "action": "GET messages/v1/users/josh/messages",
    "workflow": "a9ca2c1a-f993-420d-b851-726dafc35102",
    "scope": "messages-v1 > svc.ListenAndServe > svc.handleGetMessages",
    "message": "unable to connect to database"
}
HTTP Trace

An additional log level, "trace," is used to log incoming and outgoing HTTP calls.

The format is as follows:

{
    "time": "2023-10-01T01:00:00Z",
    "level": "trace",
    "agent": "message-v1",
    "user": "josh",
    "action": "GET messages/v1/users/josh/messages",
    "workflow": "a9ca2c1a-f993-420d-b851-726dafc35102",
    "request": "GET /message/v1/tenants/default/entities/ecf8efa3/messages/f38ce157\nAuthorization: Bearer ...\nWorkflow: 005dba5e\nAgent: profile-v1...",
    "response": "HTTP/1.1 200 OK\nDate: Mon, 27 Jul 2009 12:28:53 GMT\nWorkflow: 005dba5e\nAgent: message-v1..."
}

The Authorization header must be obfuscated in the trace message request and response.

Only HTTP headers are logged for HTTP requests and responses with binary payloads.

Reference Implementation

A reference implementation of Convention is available in ./lib with support for:

  • Go: Server-side packages for building Convention-compliant agents
  • Dart/Flutter: Client-side packages for building mobile and web applications

See lib/README.md for package documentation and quick start guide.

License

This project is licensed under the MIT License. See the LICENSE file for details. You are free to use, modify, and distribute this software as long as you adhere to the terms of the MIT License.

Directories

Path Synopsis
lib
api
cfg
ctx
db
v2

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL