You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Welcome! This is a Beginner Issue designed to help you learn the codebase.
π When this issue is complete, you will have:
β Researched gRPC interceptors and metadata in Python
β Followed SDK patterns to implement a solution
β Researched and identified appropriate programming constructs to solve the problem
β Created basic tests
β Delivered a clean, review-ready pull request
π Problem Description
Every gRPC call the Python SDK makes to a Hiero consensus node or mirror node is currently sent without any identifying information about the SDK. The consensus node has a built-in usage tracker (GrpcUsageTracker) that reads a X-User-Agent gRPC metadata header from incoming requests and uses it to log SDK type and version metrics. Without this header, the Python SDK is logged as UNKNOWN in the consensus node's telemetry.
The consensus node reads the header using this exact key:
And parses values in the format {sdk-name}/{version}, for example:
hiero-sdk-python/2.1.5
The supported SDK name for Python is hiero-sdk-python (see UserAgentType.java).
Current behavior: gRPC calls are made with no X-User-Agent header, so all Python SDK traffic appears as UNKNOWN in consensus node metrics.
Desired behavior: Every outgoing gRPC call from the Python SDK includes a X-User-Agent: hiero-sdk-python/{version} metadata header, enabling the consensus node to correctly attribute traffic.
Files to look at:
src/hiero_sdk_python/node.py β where consensus node gRPC channels are created (grpc.secure_channel, grpc.insecure_channel)
src/hiero_sdk_python/client/client.py β where mirror node gRPC channels are created
src/hiero_sdk_python/channels.py β the _Channel wrapper around gRPC channels
src/hiero_sdk_python/executable.py β where stub methods are actually called (_execute_method)
π‘ Expected Solution
Implement a gRPC client interceptor that injects the X-User-Agent: hiero-sdk-python/{version} metadata header on every outgoing gRPC call. Apply this interceptor to all channels created in the SDK (both consensus node and mirror node channels).
The header value must exactly match the format expected by the consensus node:
hiero-sdk-python/2.1.5
where the version comes from the installed package version at runtime.
UserAgent.java β how the header value is parsed (format: sdk-name/semver, e.g. hiero-sdk-python/2.1.5; "dev" is also accepted as a version)
UserAgentType.java β confirms hiero-sdk-python is a recognised SDK name
Getting the package version at runtime in Python:
importlib.metadata β standard library module; use importlib.metadata.version("hiero-sdk-python") to get the installed version at runtime
π οΈ Implementation Notes
Research how Python gRPC interceptors work before writing any code β specifically how grpc.intercept_channel() wraps a channel and how ClientCallDetails is used to pass metadata. Look at the Go SDK interceptor as an analogous example.
Create an interceptor class that implements the required interceptor interfaces and injects the X-User-Agent header into the gRPC call metadata. Consider which call types this SDK uses (unary? server-streaming?) and implement the appropriate interfaces for each.
Look up the package version at runtime using importlib.metadata. Handle the case where the version is unavailable gracefully (e.g., in a development checkout where the package is not installed β fall back to "dev").
Apply the interceptor when channels are created. Find where grpc.secure_channel() and grpc.insecure_channel() are called in node.py and client/client.py, and wrap the resulting channel with grpc.intercept_channel().
Keep it minimal β the interceptor's only job is to append this one header. It should not modify anything else about the call.
π§βπ Beginner Issue
Welcome! This is a Beginner Issue designed to help you learn the codebase.
π When this issue is complete, you will have:
β Researched gRPC interceptors and metadata in Python
β Followed SDK patterns to implement a solution
β Researched and identified appropriate programming constructs to solve the problem
β Created basic tests
β Delivered a clean, review-ready pull request
π Problem Description
Every gRPC call the Python SDK makes to a Hiero consensus node or mirror node is currently sent without any identifying information about the SDK. The consensus node has a built-in usage tracker (
GrpcUsageTracker) that reads aX-User-AgentgRPC metadata header from incoming requests and uses it to log SDK type and version metrics. Without this header, the Python SDK is logged asUNKNOWNin the consensus node's telemetry.The consensus node reads the header using this exact key:
And parses values in the format
{sdk-name}/{version}, for example:The supported SDK name for Python is
hiero-sdk-python(seeUserAgentType.java).Current behavior: gRPC calls are made with no
X-User-Agentheader, so all Python SDK traffic appears asUNKNOWNin consensus node metrics.Desired behavior: Every outgoing gRPC call from the Python SDK includes a
X-User-Agent: hiero-sdk-python/{version}metadata header, enabling the consensus node to correctly attribute traffic.Files to look at:
src/hiero_sdk_python/node.pyβ where consensus node gRPC channels are created (grpc.secure_channel,grpc.insecure_channel)src/hiero_sdk_python/client/client.pyβ where mirror node gRPC channels are createdsrc/hiero_sdk_python/channels.pyβ the_Channelwrapper around gRPC channelssrc/hiero_sdk_python/executable.pyβ where stub methods are actually called (_execute_method)π‘ Expected Solution
Implement a gRPC client interceptor that injects the
X-User-Agent: hiero-sdk-python/{version}metadata header on every outgoing gRPC call. Apply this interceptor to all channels created in the SDK (both consensus node and mirror node channels).The header value must exactly match the format expected by the consensus node:
where the version comes from the installed package version at runtime.
π Research Pointers
gRPC Python interceptors (start here):
UnaryUnaryClientInterceptorandUnaryStreamClientInterceptorgrpc.intercept_channel()β wraps an existing channel with one or more interceptors (this is the cleanest approach)How other Hiero SDKs implement this:
UnaryClientInterceptorthat appends user-agent metadata; look for the interceptor implementationHow the consensus node processes this header:
GrpcUsageTracker.javaβ the server interceptor that reads the headerUserAgent.javaβ how the header value is parsed (format:sdk-name/semver, e.g.hiero-sdk-python/2.1.5;"dev"is also accepted as a version)UserAgentType.javaβ confirmshiero-sdk-pythonis a recognised SDK nameGetting the package version at runtime in Python:
importlib.metadataβ standard library module; useimportlib.metadata.version("hiero-sdk-python")to get the installed version at runtimeπ οΈ Implementation Notes
Research how Python gRPC interceptors work before writing any code β specifically how
grpc.intercept_channel()wraps a channel and howClientCallDetailsis used to pass metadata. Look at the Go SDK interceptor as an analogous example.Create an interceptor class that implements the required interceptor interfaces and injects the
X-User-Agentheader into the gRPC call metadata. Consider which call types this SDK uses (unary? server-streaming?) and implement the appropriate interfaces for each.Look up the package version at runtime using
importlib.metadata. Handle the case where the version is unavailable gracefully (e.g., in a development checkout where the package is not installed β fall back to"dev").Apply the interceptor when channels are created. Find where
grpc.secure_channel()andgrpc.insecure_channel()are called innode.pyandclient/client.py, and wrap the resulting channel withgrpc.intercept_channel().Keep it minimal β the interceptor's only job is to append this one header. It should not modify anything else about the call.
π§ Beginner Contributors β Prerequisites & Expectations
Caution
Beginner issues are low-risk but we expect a working solution.
Important
We recommend completing at least 3 good first issues before attempting a beginner issue.
Difficulty:
Tip
You should be comfortable with:
If any of that feels unfamiliar, good first issues might still be the most rewarding path for you right now.
β±οΈ Timeline & Workflow
Typical time: ~1 week / ~8 hours
π§© Difficulty: Manageable but requires investigation and testing
π Best for: Beginner contributors
π΄ Completing this issue in 1β3 hours is a red flag
Tip
Suggested: share your proposed implementation approach as a comment before writing code to get early feedback and avoid wasted effort.
π§ͺ Testing Requirements
Important
At the beginner level, testing will be necessary but a small component.
The methods you implement should be verified (happy path at least).
Source code changes (in
src/):X-User-Agentheader valueuv run pytest tests/unit/ -vπ‘οΈ Quality & Review Standards
Beginner PRs must be working and follow best practices.
node.pyandchannels.pyβ do not introduce a new style or abstraction.β PR Quality Checklist
Before opening your PR, confirm:
Before requesting a review, confirm:
git commit -S -s -m "chore: description"β Signing guideCHANGELOG.mdentry under[Unreleased]β Changelog guideπ Workflow Quick Reference
/assignbelowπ Resources & Support
π Stuck?
Tip
Comment on this issue and describe what you have tried. A maintainer will respond.
Python SDK References:
References: