Skip to content

dev <- main sync#453

Merged
amit-gazal-thenvoi merged 106 commits into
devfrom
main
Jul 20, 2026
Merged

dev <- main sync#453
amit-gazal-thenvoi merged 106 commits into
devfrom
main

Conversation

@nir-singher-band

Copy link
Copy Markdown
Collaborator

PR Title Format

Required: PR titles must follow Conventional Commits format:
type(scope): description

Types: feat, fix, docs, style, refactor, test, chore

Examples:

  • feat(agent): add event streaming support
  • fix(api): resolve timeout handling
  • docs: update integration examples

Summary

Changes

Related Issues

Testing

  • Unit tests pass (uv run pytest tests/ --ignore=tests/integration/)
  • Pre-commit checks pass (uv run pre-commit run --all-files)
  • Integration tests pass (if applicable)

Checklist

  • PR title follows Conventional Commits format
  • Code follows project style guidelines
  • Tests added/updated as needed
  • Documentation updated as needed

AlexanderZ-Band and others added 30 commits June 16, 2026 17:47
Bridge a developer-built Agno Agent to Band: AgnoAdapter converts room
history to Agno messages, runs the agent, and replies with its text
output. Agno is model-agnostic, so the agent (model, instructions,
tools) is supplied by the developer and reused per room.

Includes AgnoHistoryConverter, lazy adapter/converter registration, the
`agno` optional-dependency extra, and a basic example with README.

Text-only skeleton: Band platform-tool wiring, tool-event conversion,
conformance registration, and tests are deferred to follow-ups.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add an agno_agent entry to the repo-root agent_config.yaml.example and
repoint the example docstring and README at it, instead of a per-example
config file that does not exist. Simplify the example's platform URL
handling.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Use RunOutput.get_content_as_string() instead of assuming response.content
is a str, so agents configured with structured output (Pydantic BaseModel)
or dict/list output are serialized to JSON rather than crashing on .strip().
Log at debug when non-text content is sent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Declare SUPPORTED_EMIT={Emit.EXECUTION} and, when enabled via
AdapterFeatures(emit={Emit.EXECUTION}), report the Agno agent's own tool
executions to the room as tool_call/tool_result events after each run,
read from RunOutput.tools. Mirrors the event shape used by the other
adapters. Reporting failures are logged, not raised.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
02_tool_reporting.py builds an Agno agent with its own tool and enables
AdapterFeatures(emit={Emit.EXECUTION}) so tool_call/tool_result events are
posted to the room. Listed in the examples README.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Log the message-handling flow at INFO (handling message, reporting tool
executions, sending reply) with verbose details (input size, tool args/
results, edge cases) at DEBUG. Verified live against the platform.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Declare SUPPORTED_CAPABILITIES={MEMORY, CONTACTS} and, when those capabilities
are enabled, wire Band's memory/contact tools into the Agno agent as Agno
Functions. Each tool's entrypoint runs the Band tool via execute_tool_call,
binding the per-room tools handle through a ContextVar so a single shared agent
serves concurrent rooms. Base tools (send_message, participants) stay
adapter-driven and are filtered out. Tools are wired once on the first message.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Deep-copy the provided Agno agent in on_started and wire Band tools onto the
copy, so the adapter never mutates the caller's agent object. Guard on_message
for the not-yet-started case and handle add_tool's callable-factory rejection.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When the caller enables Capability.MEMORY (so the adapter exposes Band memory
tools to the agent) and the Agno agent also manages its own memory
(update_memory_on_run or enable_agentic_memory), raise a UserWarning at
construction time (stacklevel points at the caller). Using warnings.warn rather
than logging makes the conflict filterable and escalatable to an error.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add AgnoOutputAdapter (reads role/content off agno Message objects) and
register agno in the converter and adapter config registries:
- converter: filters_own_messages=False, skips_tool_events=True (text-only)
- adapter: inject a stand-in agent in the factory; no model/prompt or custom
  tools, so assert adapter-level state (agent=None, _band_tools_wired=False)

Resolves the config-drift failure for the new agno modules.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Band delivers rehydrated platform history only on session bootstrap; later
messages arrive with empty history. The adapter previously rebuilt input from
the history arg each call, so it dropped all context after the first turn.

Accumulate a per-room transcript (self._message_history) seeded from history on
bootstrap and appended with each user message and assistant reply, and feed it
to Agno on every run. Restart re-seeds from the rehydrated history; on_cleanup
drops the room's transcript.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Register a create_agno_adapter factory (Claude model via ANTHROPIC_API_KEY)
and add "agno" to the parametrized adapter_entry fixture so the smoke and
tool-execution E2E tests cover it alongside the other adapters.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reply with mentions=[msg.sender_id]; the SDK resolves handles/names/IDs from
the string form. Avoids the list[dict] mentions deprecation warning.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
claude-3-haiku-20240307 is retired (Anthropic 404). Default e2e_anthropic_model
to claude-haiku-4-5-20251001 so the Anthropic-family adapter E2E tests
(anthropic, claude_sdk, agno) authenticate against a current model.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The converter now carries tool_call/tool_result events through rehydration:
tool calls become an assistant message with batched OpenAI-style tool_calls,
and results become tool-role messages paired by tool_call_id. This is Agno's
own history shape, so prior tool turns round-trip back through arun().

Dispatch uses match/case with a focused builder per event type. Flips the
conformance skips_tool_events flag and extends AgnoOutputAdapter to inspect
tool-call names/args.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the per-method `from agno.models.message import Message` statements with
a single `_message_class` cached_property on the converter. Keeps the module
importable without agno installed, raises one clear ImportError on use, and lets
call sites read as `self._message_class(role=..., ...)`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Converter logs event->message conversion counts. Adapter logs the resolved
emit/capability features at startup and the bootstrap history-seed size, so
rehydration and feature config are visible at DEBUG.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Prefix every on_message/tool-report log with "Room <room_id> msg <msg_id>" and
log the sender id on intake and the mentions on reply, so a message can be
traced end-to-end across the adapter.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
03_tom_and_jerry.py spins up two Agno-backed Band agents (Tom and Jerry) with
distinct personalities in one process via asyncio.gather, reusing the shared
character prompts. They reply in character when mentioned in a shared room
(the Agno adapter is reply-only, so they don't auto-invite like the CrewAI
version). Adds tom/jery entries to agent_config.yaml.example and the README.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Skip band_send_message/band_send_event in _report_tool_executions: their
effect is already a visible room message/event, so reporting them would
double-record the reply (and duplicate it on rehydration). Adds the constant
the filter referenced.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Split the long on_message into a short orchestrator plus single-concern
helpers: _build_run_input (assemble transcript), _run_agent (run + ContextVar
bind + error handling), _persist_turn (continuity), and _send_reply (fallback
reply). Extract _emit_execution from _report_tool_executions, tighten
_make_band_entrypoint's return type, and make room_id/msg_id keyword-only on
the reporting/run helpers. No behavior change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the inline ContextVar set/try/finally-reset in _run_agent with a
_bind_room_tools context manager, so the "room's tools are bound for the
duration of the run" before/after is named, reusable, and can't drift. Reset
still happens on success and error. No behavior change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add agno_message_class() and agno_function_class() (lru_cached, with a shared
_require_agno helper) in band.converters.agno — the single home for the
optional-dependency type imports. The converter and the adapter both use them,
removing the duplicated per-class _message_class accessors and scattered
`from agno...import` statements.

Also tidy _build_run_input: collapse the room-history init with setdefault, drop
the verbose bootstrap-seed log, and surface bootstrap state on the intake log
instead. No behavior change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Build Band tools with a positive walrus guard (if name := fn.get("name")) and
switch the converter's match default from continue to pass. Same behavior,
no continue.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Agno 2.6.16 uses any(msg.from_history for msg in input) to decide whether the
input already carries history; our converter built rehydrated Band history with
the default from_history=False, so an agent with its own db/session history could
re-add stored history on top of Band history (duplicate context / repeated tool
transcripts on bootstrap). Tag all converter-produced messages from_history=True;
the adapter's current-turn message stays False.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A refactor dropped the set_agent_name call, leaving the converter's _agent_name
empty so the own-agent check never matched — on restart the agent's own past
replies rehydrated as "[Name]: ..." user messages instead of assistant turns.
Restore the sync in on_started.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
AlexanderZ-Band and others added 28 commits June 21, 2026 12:51
…ocators

The thoughts scenario reused a persisted room, so accumulated repeats of
the same step-by-step question let Claude skip extended thinking, leaving
reasoning_content empty -> no thought event -> a flaky failure. Allocate a
fresh room instead, matching the database-restart scenario.

Also drop the thin agno_multi_room / agno_thoughts_room / agno_database_room
fixture wrappers; each scenario calls the allocator directly (mirroring
test_context_persistence), keeping the room name and the "why this allocator"
rationale at the call site.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When an adapter is configured with emit or capability values it doesn't
implement, the base SimpleAdapter now emits a UserWarning in addition to
the existing log line, so the misconfiguration surfaces even when logging
is not at WARNING level.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(sdk): adapters report boolean activity (working) state to the pl…
Switch release workflow to band-ai/.github/actions/generate-app-token@v1
and remove the promote-dev-to-main workflow that relied on the local
GithubToken action.
chore(ci): use shared band-ai app token action
…components--band-sdk

chore: release band-sdk 1.1.0
Drop the band-ai/.github composite action (inaccessible from this public
repo) and call actions/create-github-app-token@v3 inline. Also fix the
broken steps.app_token_generator.outputs.token reference left over from
the earlier rename.

Requires secrets.APP_PRIVATE_KEY to be stored as raw PEM.
…ction

ci: use actions/create-github-app-token@v3 directly
…-for-unsupported-adapter-feature-flags-INT-880

feat: raise a visible UserWarning for unsupported adapter feature flags
Address PR review feedback:

- Inject the Band-registered identity ("You are {name}, {description}.")
  into the agent prompt at startup via render_system_prompt, matching the
  other adapters. Previously the fetched agent_name/description were only
  used for logging and the converter, so the model never saw its Band
  identity. Lock it in with a test assertion.
- Correct the examples README: the adapter does not send a text fallback
  (that was dropped earlier); the agent must call band_send_message or it
  stays silent. Reword the Overview and Note accordingly.
- Split the combined Tom-and-Jerry example into 03_tom_agent.py and
  04_jerry_agent.py (separate processes) to match the other adapters and
  demonstrate cross-adapter room communication; renumber memory/db
  examples to 05/06 and point agent_config.yaml.example at the shared
  tom_agent/jerry_agent entries.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Agno is model-agnostic, but the `agno` optional extra pinned `anthropic`,
forcing the Claude SDK onto everyone who installed `band-sdk[agno]` even
when using OpenAI/Gemini/Groq. Anthropic was only ever the examples' default.

- Drop `anthropic` from the `agno` extra (regen uv.lock); it stays in `dev`
  so tests/CI are unaffected.
- Each example declares its provider (`anthropic`) in its own PEP 723
  metadata, so `uv run examples/agno/<file>.py` still pulls it automatically.
- examples README: add a Model providers table (import / package / API key
  for anthropic, openai, google, groq), an Installation section covering both
  the `uv run` and `uv sync --extra agno` paths, and an OpenAI Quick Start
  snippet alongside the Claude one.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…-INT-856

feat: sdk add agno adapter python int 856
…pter-python-INT-856

revert: sdk add agno adapter python int 856"
…for-unsupported-adapter-feature-flags-INT-880
…userwarning-for-unsupported-adapter-feature-flags-INT-880

revert: raise a visible UserWarning for unsupported adapter feature flags"
…components--band-sdk

chore(main): release band-sdk 1.2.0
@amit-gazal-thenvoi
amit-gazal-thenvoi merged commit 559ae53 into dev Jul 20, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants