The problem is a double tweak.
python-bitcoinutils applies a BIP86 tweak internally when you call get_taproot_address(). If you have already applied a BIP86 tweak manually to the aggregate key, the on-chain output key has been tweaked twice.
Local schnorr_verify passes because it checks against the key you provide — it does not know what is actually on-chain. Bitcoin Core checks against the real output key, which has two tweaks applied. The signature built with only one tweak is invalid against that key.
The fix: SessionContext must carry both tweaks explicitly:
pythonsession_ctx = SessionContext(
aggnonce, pubkeys,
[tweak1, tweak2], # both tweaks required
[True, True],
msg
)
This is not a bug — the library handles BIP86 automatically for typical single-key use. In MuSig2, where you manage tweaks manually, the abstraction leaks.
Verified on testnet: af6fdae8…9d1f












