Provider
A Provider gives an agent access to an external service — GitHub, Telegram, AWS, GCP, Azure, Slack, or any HTTP API. The agent's requests to that service are transparently intercepted by the Pai sidecar, which injects credentials and enforces policy.
The agent never holds real credentials. It makes requests normally, and Pai handles authentication behind the scenes.
pai apply -f provider.yaml
pai get services
pai delete service <name>
How it works
When a provider is attached to an agent:
- DNS for the provider's hostname resolves to
127.0.0.1(the sidecar) inside the agent pod - The sidecar intercepts the HTTPS request
- Policy is checked — if denied, the request is blocked with HTTP 403
- Credentials are injected (Bearer token, SigV4 signature, OAuth2 token, etc.)
- The real request is forwarded to the external service
Field reference
| Field | Required | Description |
|---|---|---|
type | Yes | Provider type (see below) |
host | No | Hostname to intercept. Defaults to the provider's standard host |
auth.type | Yes | Authentication method |
auth.secretRef | Yes | Name of the Secret holding credentials |
auth.secretKey | No | Key within the Secret (default: token) |
auth.agentEnvVar | No | Env var injected into the agent with a dummy value so libraries initialize correctly |
config.region | No | Cloud region (AWS, Azure) |
config.project | No | GCP project ID |
config.tenantId | No | Azure AD tenant ID |
config.services | No | Restrict to specific cloud services (e.g. [s3, sqs]) |
policy.allow | No | Allowed actions. ["*"] = allow all |
policy.deny | No | Denied actions (takes precedence over allow) |
policy.httpRules | No | Raw HTTP method + path rules (see below) |
scope.repositories | No | Allowed GitHub repositories |
scope.channels | No | Allowed Slack channels |
scope.resources | No | Allowed cloud resource patterns (ARNs, paths) |
audit.logRequests | No | Log every API call (default: true) |
audit.enforcement | No | enforce (default) blocks violations · audit logs but allows — useful for testing a new policy |
Provider types
type | auth.type | Description |
|---|---|---|
github | pat | GitHub Personal Access Token |
telegram | bot-token | Telegram Bot API |
slack | bot-token | Slack Bot token |
aws | aws-sigv4 | AWS SigV4 request signing |
azure | azure-client-credentials | Azure OAuth2 client credentials |
gcp | gcp-service-account | GCP service account JSON key |
Examples
GitHub
apiVersion: pai.io/v1
kind: Provider
metadata:
name: github-writer
spec:
type: github
auth:
type: pat
secretRef: github-pat
policy:
allow:
- pulls:create
- pulls:comment
- issues:read
- contents:read
deny:
- admin:*
scope:
repositories:
- "myorg/repo-a"
- "myorg/repo-b"
Secret required:
pai add secret github-pat --from-literal token=ghp_YOUR_TOKEN
Telegram
apiVersion: pai.io/v1
kind: Provider
metadata:
name: telegram-bot
spec:
type: telegram
host: api.telegram.org
auth:
type: bot-token
secretRef: telegram-token
secretKey: token
agentEnvVar: TELEGRAM_BOT_TOKEN
policy:
allow: ["*"]
Secret required:
pai add secret telegram-token --from-literal token=YOUR_BOT_TOKEN
AWS S3
apiVersion: pai.io/v1
kind: Provider
metadata:
name: s3-reader
spec:
type: aws
auth:
type: aws-sigv4
secretRef: aws-creds
config:
region: us-east-1
services: [s3]
policy:
allow:
- s3:GetObject
- s3:ListBucket
deny:
- s3:DeleteObject
- s3:PutObject
scope:
resources:
- "arn:aws:s3:::my-bucket/*"
Secret required:
pai add secret aws-creds \
--from-literal access_key_id=AKIAIOSFODNN7EXAMPLE \
--from-literal secret_access_key=wJalrXUtnFEMI...
GCP
apiVersion: pai.io/v1
kind: Provider
metadata:
name: gcp-storage
spec:
type: gcp
auth:
type: gcp-service-account
secretRef: gcp-sa-key
config:
project: my-gcp-project
services: [storage]
policy:
allow:
- storage.objects.get
- storage.objects.list
deny:
- storage.objects.delete
Secret required:
pai add secret gcp-sa-key --from-literal key.json="$(cat service-account.json)"
Azure
apiVersion: pai.io/v1
kind: Provider
metadata:
name: azure-storage
spec:
type: azure
auth:
type: azure-client-credentials
secretRef: azure-sp-creds
config:
tenantId: "your-tenant-id"
services: [storage]
policy:
allow:
- "Microsoft.Storage/storageAccounts/read"
deny:
- "Microsoft.Storage/storageAccounts/delete"
Secret required:
pai add secret azure-sp-creds \
--from-literal client_id=YOUR_CLIENT_ID \
--from-literal client_secret=YOUR_CLIENT_SECRET
Attaching a provider to an agent
spec:
providers:
- github-writer
- telegram-bot
Policy
Action-based policy
Action names follow provider conventions:
| Provider | Format | Examples |
|---|---|---|
| GitHub | resource:action | pulls:create, issues:read, admin:* |
| AWS | service:Action | s3:GetObject, sqs:SendMessage |
| Azure | Provider/resource/action | Microsoft.Storage/storageAccounts/read |
| GCP | service.resource.action | storage.objects.get |
| Telegram | method name | sendMessage, getUpdates |
HTTP-level rules
Use httpRules for fine-grained path/method control, or for services without a provider plugin:
policy:
allow: ["*"]
httpRules:
- methods: [GET]
paths: ["/repos/*/issues", "/repos/*/pulls"]
effect: allow
- methods: [POST, PUT, PATCH, DELETE]
paths: ["*"]
effect: deny
Deny rules are checked first. If httpRules is defined but no rule matches, the request is denied.
Audit mode
Roll out a new policy safely without blocking live traffic:
audit:
logRequests: true
enforcement: audit # switch to "enforce" once you're confident
Policy changes (policy, httpRules, audit, scope) take effect on running agents within ~1 minute without a restart.