Typing¶
Alloy provides precise static types for commands and ask via .pyi
stubs.
- Use
@command(output=T)
for a typed resultT
. - If you omit
output
, the command returnsstr
(andAwaitable[str]
for async). - Parameters are preserved (ParamSpec), so your decorated command keeps the same args.
- Streaming always yields text chunks (
str
).
Basics
from alloy import command, ask
@command(output=float)
def extract_price(text: str) -> str:
return f"Extract price from: {text}"
price: float = extract_price("the price is 5.99")
# No output → str
@command
def summarize(text: str) -> str:
return f"Summarize: {text}"
summary: str = summarize("hello")
Async
from dataclasses import dataclass
from typing import Awaitable, AsyncIterable
from alloy import command
@dataclass
class User:
name: str
id: int
@command(output=User)
async def fetch_user(name: str) -> str:
return f"Find user named {name} and return JSON"
user_awaitable: Awaitable[User] = fetch_user()
# after await -> User
# Streaming
chunks: AsyncIterable[str] = fetch_user.stream()
# Convenience
user_awaitable2: Awaitable[User] = fetch_user.async_()
Ask namespace
from typing import Iterable, AsyncIterable
from alloy import ask
text: str = ask("Explain in one sentence.")
sync_stream: Iterable[str] = ask.stream("Explain briefly.")
async_stream: AsyncIterable[str] = ask.stream_async("Explain briefly.")
Notes
- Import from alloy
: from alloy import command, ask
. Importing through submodules bypasses the stubs.
- Alloy does not infer from your function’s return annotation. The decorated function must be annotated -> str
(it returns a prompt string). The decorator’s output
parameter controls the command’s return type; when omitted, the return type is str
.