Astami
A modern, async-first Python client for the Asterisk Manager Interface (AMI).
Features
- Modern Python: Built for Python 3.10+ with full type hints
- Async & Sync: Both
AsyncAMIClientandAMIClient(sync wrapper) available - Context Managers: Automatic connection handling and cleanup
- No Dependencies: Pure Python, no external dependencies
- Fully Typed: Complete type annotations for IDE support
- Convenience Methods: High-level methods for common operations
Installation
pip install astami
Quick Start
Synchronous Usage
from astami import AMIClient
with AMIClient("localhost", 5038, "admin", "secret") as ami:
# Execute CLI commands
response = ami.command("core show version")
print(response.output)
# Reload configuration
ami.reload("pjsip")
Asynchronous Usage
import asyncio
from astami import AsyncAMIClient
async def main():
async with AsyncAMIClient("localhost", 5038, "admin", "secret") as ami:
# Execute CLI commands
response = await ami.command("core show version")
print(response.output)
# Reload configuration
await ami.reload("pjsip")
asyncio.run(main())
API Reference
Client Classes
AsyncAMIClient
The async client for use in asyncio applications.
AsyncAMIClient(
host: str = "127.0.0.1",
port: int = 5038,
username: str = "",
secret: str = "",
timeout: float = 10.0,
)
AMIClient
Synchronous wrapper for use in threaded applications, Celery tasks, etc.
AMIClient(
host: str = "127.0.0.1",
port: int = 5038,
username: str = "",
secret: str = "",
timeout: float = 10.0,
)
Response Object
All methods return an AMIResponse object:
@dataclass
class AMIResponse:
raw: str # Raw response string
action_id: str # ActionID from the request
response: str # Response status (Success, Error, etc.)
message: str # Message from Asterisk
data: dict[str, str] # All key-value pairs
output: list[str] # Output lines (for Command actions)
@property
def success(self) -> bool:
"""True if response indicates success"""
Available Methods
CLI Commands
# Execute any CLI command
response = ami.command("sip show peers")
for line in response.output:
print(line)
Asterisk Database (AstDB)
# Store a value
ami.database_put("family", "key", "value")
# Retrieve a value
response = ami.database_get("family", "key")
# Delete a key
ami.database_del("family", "key")
# Delete entire family
ami.database_deltree("family")
Call Origination
# Originate to dialplan
ami.originate(
channel="PJSIP/1000",
context="default",
exten="1001",
priority=1,
caller_id="Test Call <1234>",
variables={"VAR1": "value1", "VAR2": "value2"},
)
# Originate to application
ami.originate(
channel="PJSIP/1000",
application="Playback",
data="hello-world",
)
Channel Operations
# Hangup a channel
ami.hangup("PJSIP/1000-00000001")
# Redirect a channel
ami.redirect(
channel="PJSIP/1000-00000001",
context="default",
exten="1002",
priority=1,
)
# Get channel variable
response = ami.get_var("PJSIP/1000-00000001", "CALLERID(num)")
# Set channel variable
ami.set_var("PJSIP/1000-00000001", "MY_VAR", "my_value")
Configuration Reload
# Reload specific module
ami.reload("pjsip")
ami.reload("dialplan")
# Reload all
ami.reload()
Raw Actions
For actions not covered by convenience methods:
response = ami.send_action({
"Action": "QueueStatus",
"Queue": "support",
})
Error Handling
from astami import AMIClient, AMIError
try:
with AMIClient("localhost", 5038, "admin", "wrong_password") as ami:
ami.command("core show version")
except AMIError as e:
print(f"AMI Error: {e}")
if e.response:
print(f"Response: {e.response.message}")
Use Cases
Celery Tasks
from celery import shared_task
from astami import AMIClient, AMIError
@shared_task
def reload_dialplan(server_host: str) -> bool:
try:
with AMIClient(server_host, 5038, "admin", "secret") as ami:
response = ami.command("dialplan reload")
return response.success
except AMIError as e:
logger.error(f"AMI error: {e}")
return False
Django Management Command
from django.core.management.base import BaseCommand
from astami import AMIClient
class Command(BaseCommand):
help = "Show Asterisk version"
def handle(self, *args, **options):
with AMIClient("localhost", 5038, "admin", "secret") as ami:
response = ami.command("core show version")
self.stdout.write(self.style.SUCCESS(response.output[0]))
Async Web Application (FastAPI)
from fastapi import FastAPI
from astami import AsyncAMIClient
app = FastAPI()
@app.get("/asterisk/version")
async def get_version():
async with AsyncAMIClient("localhost", 5038, "admin", "secret") as ami:
response = await ami.command("core show version")
return {"version": response.output[0] if response.output else "Unknown"}
Configuration
Asterisk manager.conf
Ensure your Asterisk server has AMI enabled in /etc/asterisk/manager.conf:
[general]
enabled = yes
port = 5038
bindaddr = 0.0.0.0
[admin]
secret = your_secret_here
read = all
write = all
After changes, reload the manager module:
asterisk -rx "manager reload"
Why Astami?
- Python 3.10+: Uses modern Python features like
matchstatements, union types with|, and proper async/await patterns - No Deprecated APIs: Doesn't use deprecated asyncio patterns that break in Python 3.10+
- Lightweight: No dependencies beyond the Python standard library
- Type Safe: Full type hints for better IDE support and fewer bugs
- Well Tested: Comprehensive test suite
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT License - see LICENSE for details.
Credits
Developed by Real World Technology Solutions.
Metadata
Release files for astami 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| astami-1.1.0.tar.gz | 10.4 kB | With provenance | Details for astami-1.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| astami-1.1.0-py3-none-any.whl | Python 3 | none | any | Details for astami-1.1.0-py3-none-any.whl |
Total release size: 21.6 kB
Release files / astami-1.1.0.tar.gz
| Download URL | astami-1.1.0.tar.gz |
|---|---|
| Size | 10.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
022ab212aac59839dfa0c2442c992a8aad2b71d394faec6e8b8ad852c0414ba9
|
|
BLAKE2b-256 checksum How to use checksums |
59a96f2110114f5a55030445766db89eb3489058dbadfb8e993ddbb521910da3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 31, 2026.
Transparency logRelease files / astami-1.1.0-py3-none-any.whl
| Download URL | astami-1.1.0-py3-none-any.whl |
|---|---|
| Size | 11.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3011cd42d88504c7af9ba5885eaa64850b7f1183150b2bffe28b0f8df6d5d5ae
|
|
BLAKE2b-256 checksum How to use checksums |
356e5d5e7661bbcda4baecf4e365f09ff03fe96056e108fd5a0cbec609193912
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 31, 2026.
Transparency logSecurity for astami 1.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for astami-1.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 31, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.