Vendor Agnostic Agent SDK
Project description
glyph
Minimal vendor-agnostic async SDK that normalizes Claude Agent SDK and OpenAI Agents SDK output into one event stream.
Install
pip install glyph-agents
# or for local development
pip install -e .
Requires Python >=3.10.
Quickstart (query helper)
import asyncio
from glyph import AgentOptions, AgentQueryCompleted, AgentText, query
async def main() -> None:
options = AgentOptions(
model="gpt-4.1-mini", # or "claude-haiku-4-5"
instructions="You are concise and accurate.",
)
async for event in query(
prompt="In one sentence, explain what an API is.",
options=options,
):
if isinstance(event, AgentText):
print(event.text, end="")
elif isinstance(event, AgentQueryCompleted):
print("\n\nis_error:", event.is_error)
print("usage:", event.usage)
print("total_cost_usd:", event.total_cost_usd)
if __name__ == "__main__":
asyncio.run(main())
Streaming with GlyphClient
Use GlyphClient when you want explicit control of turn lifecycle methods:
query(...)thenreceive_response(...): send one prompt now, stream that prompt's events right after.query_streamed(...): same behavior as above, but in one call.query_and_receive_response(...): run one prompt and return all events at once (no streaming loop).receive_messages(...): use this when you queued multiple prompts withquery(...)first and want to drain them in order from a single stream.
import asyncio
from glyph import AgentOptions, AgentQueryCompleted, AgentText, AgentThinking, GlyphClient
async def main() -> None:
options = AgentOptions(model="gpt-4.1-mini")
async with GlyphClient(options) as client:
async for event in client.query_streamed("List two benefits of unit tests."):
if isinstance(event, AgentThinking):
print("[thinking]", event.text)
elif isinstance(event, AgentText):
print(event.text, end="")
elif isinstance(event, AgentQueryCompleted):
print("\n\n[done]", event.is_error, event.stop_reason, event.usage)
if __name__ == "__main__":
asyncio.run(main())
Event Types
All APIs stream normalized AgentEvent values:
AgentText: visible assistant text segmentsAgentThinking: reasoning/thinking segments when availableAgentToolCall: structured tool invocation requestsAgentToolResult: structured tool invocation resultsAgentQueryCompleted: end-of-turn status (is_error,stop_reason,usage,total_cost_usd,extra)
Backend failures are surfaced as AgentQueryCompleted(is_error=True, ...).
AgentOptions
AgentOptions is the shared configuration surface:
model(required): determines backend automaticallyinstructions: system prompt / instructionsname: OpenAI agent display name (default:"Assistant")cwd: workspace root for tool accessallowed_tools: activation allow-list using Claude-style tool names (Read,Write,Edit,Glob,Grep,Bash,WebSearch,WebFetch).- Any tool not listed is disabled.
None/empty means no built-in tools are activated.
permission:PermissionPolicy(edit_ask=True, execute_ask=True, web_ask=True)enables interactive confirmation per capability.edit_askapplies to file mutation actions (Write/Edit).execute_askapplies to command actions (Bash).web_askapplies to web actions (WebSearch/WebFetch) (WebSearchask is not supported for OpenAI models).- Flags default to
False, so capabilities are auto-allowed when the corresponding tool is active.
approval_handler_edit: custom approval callback for edit/write actionsapproval_handler_execute: custom approval callback for command execution actionsapproval_handler_web: custom approval callback for web actions (WebSearch/WebFetch)max_turns: backend turn cap overridereasoning_effort/reasoning_summary: OpenAI-only reasoning controls
Approval Handlers (edit vs execute)
When permissions are set to ask, Glyph can call capability-specific approval handlers:
approval_handler_edit: used forWrite/Editstyle operationsapproval_handler_execute: used forBashstyle operationsapproval_handler_web: used forWebSearch/WebFetchstyle operations
If a handler is missing, Glyph falls back to interactive TTY approval prompts. In non-interactive contexts (server/worker/CI), missing handlers will cause the action to be denied with a clear error message.
from glyph import AgentOptions, ApprovalDecision, PermissionPolicy
def approve_edit(req):
# req.capability == "edit"
return ApprovalDecision(allow=True)
def approve_execute(req):
# req.capability == "execute"
commands = (req.payload or {}).get("commands", [])
allowed = all("rm -rf" not in c for c in commands)
return ApprovalDecision(
allow=allowed,
reason=None if allowed else "Dangerous command blocked",
)
options = AgentOptions(
model="gpt-5.4",
permission=PermissionPolicy(edit_ask=True, execute_ask=True, web_ask=True),
approval_handler_edit=approve_edit,
approval_handler_execute=approve_execute,
)
Backend Resolution
resolve_backend(options) infers backend from model:
- Claude if model contains
claudeoranthropic - OpenAI if model starts with
gpt-,o1,o3,o4, orchatgpt
If inference fails, resolve_backend raises ValueError.
Prompt Input Shape
- Claude backend accepts
stror async iterable prompt blocks (Claude-compatible content blocks). - OpenAI backend currently supports
strprompts only.
Examples
Run from repository root:
python examples/01_query_helper.py
python examples/02_query_streamed.py
python examples/03_query_then_receive_response.py
python examples/04_query_and_receive_response.py
python examples/05_receive_messages_multiple_turns.py
python examples/06_sessions.py
python examples/07_tools_and_permissions.py
python examples/08_openai_reasoning.py
python examples/09_resolve_backend.py
python examples/10_claude_async_prompt_iterable.py
python examples/11_websearch_tool_calls.py
python examples/12_claude_webfetch_tool_calls.py
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file glyph_agents-0.1.0a1.tar.gz.
File metadata
- Download URL: glyph_agents-0.1.0a1.tar.gz
- Upload date:
- Size: 28.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7d66fcec09ffafe2967de94d51b845169b50876d45377ff2134f8a89a6821137
|
|
| MD5 |
0d66aab926c7b2c8230d5cf5e929336c
|
|
| BLAKE2b-256 |
bbf8d968cc79392843bfed21d87bef13a234ace7f9d1f2bca9580de1cb00e316
|
File details
Details for the file glyph_agents-0.1.0a1-py3-none-any.whl.
File metadata
- Download URL: glyph_agents-0.1.0a1-py3-none-any.whl
- Upload date:
- Size: 33.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3bccaff0b9dae5a6782c2166d68916e2d69b79a4895aee71c965578bec39f183
|
|
| MD5 |
cd1d7c0fd2434b1e762a29222c3f1343
|
|
| BLAKE2b-256 |
3b0806ea58fa9c0cafa2c5a1c363e53827220dbd1d74e05a4b357435f5c5a26f
|