Field behavior documentation
When defining fields in protocol buffers, it is customary to explain to users certain aspects of the field’s behavior (such as whether it is required or optional). Additionally, it can be useful for other tools to understand this behavior (for example, to optimize client library signatures).
Guidance
Section titled “Guidance”APIs use the aep.api.field_info
annotation to describe well-understood field
behavior, such as a field being required or immutable.
// The audio data to be recognized.RecognitionAudio audio = 2 [(aep.api.field_info) = { field_behavior: [FIELD_BEHAVIOR_REQUIRED]}];
- APIs must apply the
aep.api.field_info
annotation on every field on a message or sub-message used in a request. - The annotation must include any aep.api.FieldBehavior values that
accurately describe the behavior of the field.
FIELD_BEHAVIOR_UNSPECIFIED
must not be used.
- APIs must at minimum use one of
FIELD_BEHAVIOR_REQUIRED
,FIELD_BEHAVIOR_OPTIONAL
, orFIELD_BEHAVIOR_OUTPUT_ONLY
.
field behavior of nested messages
Section titled “field behavior of nested messages”aep.api.field_info
annotations on a nested message are independent of the
annotations of the parent.
For example, a nested message can have a field behavior of
FIELD_BEHAVIOR_REQUIRED
while the parent field can be
FIELD_BEHAVIOR_OPTIONAL
:
message Title { string text = 1 [(aep.api.field_info) = { field_behavior: [FIELD_BEHAVIOR_REQUIRED] }];}
message Slide { Title title = 1 [(aep.api.field_info) = { field_behavior: [FIELD_BEHAVIOR_OPTIONAL] }];}
In the case above, if a title
is specified, the text
field is required.
Vocabulary
Section titled “Vocabulary”Immutable
Section titled “Immutable”The use of FIELD_BEHAVIOR_IMMUTABLE
indicates that a field on a resource
cannot be changed after it’s creation. This can apply to either fields that are
input or outputs, required or optional.
When a service receives an immutable field in an update request (or similar),
even if included in the update mask, the service should ignore the field if
the value matches, but should error with INVALID_ARGUMENT
if a change is
requested.
Potential use cases for immutable fields (this is not an exhaustive list) are:
- Attributes of resources that are not modifiable for the lifetime of the application (e.g. a disk type).
Input only
Section titled “Input only”The use of FIELD_BEHAVIOR_INPUT_ONLY
indicates that the field is provided in
requests and that the corresponding field will not be included in output.
Additionally, a field should only be described as input only if it is a
field in a resource message or a field of a message included within a resource
message. Notably, fields in request messages (a message which only ever acts as
an argument to an RPC, with a name usually ending in Request
) should not
be described as input only because this is already implied.
Potential use cases for input only fields (this is not an exhaustive list) are:
- The
ttl
field as described in AEP-214.
Optional
Section titled “Optional”The use of FIELD_BEHAVIOR_OPTIONAL
indicates that a field is not required.
A field may be described as optional if it is a field on a request message
(a message that is an argument to an RPC, usually ending in Request
), or a
field on a submessage.
Output only
Section titled “Output only”The use of FIELD_BEHAVIOR_OUTPUT_ONLY
indicates that the field is provided in
responses, but that including the field in a message in a request does nothing
(the server must clear out any value in this field and must not throw
an error as a result of the presence of a value in this field on input).
Similarly, services must ignore the presence of output only fields in
update field masks (see: AEP-161).
Additionally, a field should only be described as output only if it is a
field in a resource message, or a field of a message farther down the tree.
Notably, fields in response messages (a message which only ever acts as a
return value to an RPC, usually ending in Response
) should not be
described as output only because this is already implied.
Output only fields may be set to empty values if appropriate to the API.
Potential use cases for output only fields (this is not an exhaustive list) are:
- Create or update timestamps.
- Derived or structured information based on original user input.
- Properties of a resource assigned by the service which can not be altered.
Required
Section titled “Required”The use of FIELD_BEHAVIOR_REQUIRED
indicates that the field must be
present (and set to a non-empty value) on the request.
A field should only be described as required if either:
- It is a field on a resource that a user provides somewhere as input.
- It is a field on a request message (a message that is an argument to an RPC,
with a name usually ending in
Request
). In this case, a value must be provided as part of the request, and failure to do so must cause an error (usuallyINVALID_ARGUMENT
).
Fields should not be described as required in order to signify:
- A field which will always be present in a response.
- A field which is conditionally required in some situations.
- A field on any message (including messages that are resources) which is never used as user input.
Unordered List
Section titled “Unordered List”The use of FIELD_BEHAVIOR_UNORDERED_LIST
on a repeated field of a resource
indicates that the service does not guarantee the order of the items in the
list.
A field should be described as an unordered list if the service does not guarantee that the order of the elements in the list will match the order that the user sent, including a situation where the service will sort the list on the user’s behalf.
Backwards compatibility
Section titled “Backwards compatibility”Adding or changing aep.api.field_info
values can represent a semantic change
in the API that is perceived as incompatible for existing clients. The
following are examples of backwards incompatible changes with
aep.api.field_info
:
- Adding
FIELD_BEHAVIOR_REQUIRED
to an existing field previously consideredFIELD_BEHAVIOR_OPTIONAL
(implicitly or otherwise) - Adding a new field annotated as
FIELD_BEHAVIOR_REQUIRED
to an existing request message - Adding
FIELD_BEHAVIOR_OUTPUT_ONLY
to an existing field previously accepted as input - Adding
FIELD_BEHAVIOR_INPUT_ONLY
to an existing field previously emitted as output - Adding
FIELD_BEHAVIOR_IMMUTABLE
to an existing field previously considered mutable - Removing
FIELD_BEHAVIOR_OUTPUT_ONLY
from an existing field previously ignored as input
There are some changes that are backwards compatible, which are as follows:
- Adding
FIELD_BEHAVIOR_OPTIONAL
to an existing field - Changing from
FIELD_BEHAVIOR_REQUIRED
toFIELD_BEHAVIOR_OPTIONAL
on an existing field - Removing
FIELD_BEHAVIOR_REQUIRED
from an existing field - Removing
FIELD_BEHAVIOR_INPUT_ONLY
from an existing field previously excluded in responses - Removing
FIELD_BEHAVIOR_IMMUTABLE
from an existing field previously considered immutable
Rationale
Section titled “Rationale”Required set of annotations
Section titled “Required set of annotations”A field used in a request message must be either an input or an output.
In the case of an output, the FIELD_BEHAVIOR_OUTPUT_ONLY
annotation is
sufficient.
In the case of an input, a field is either required or optional, and therefore
should have at least the FIELD_BEHAVIOR_REQUIRED
or FIELD_BEHAVIOR_OPTIONAL
annotation, respectively. Only providing FIELD_BEHAVIOR_INPUT_ONLY
does not
convey the necessity of the field, so specifying either
FIELD_BEHAVIOR_REQUIRED
or FIELD_BEHAVIOR_OPTIONAL
is still necessary.
Requiring field behavior
Section titled “Requiring field behavior”By including the field behavior annotation for each field, the overall behavior that the resource exhibits is more clearly defined. Clearly defined field behavior improves programmatic clients and user understanding.
Requiring the annotation also forces the API author to explicitly consider the behavior when initially authoring of the API.
Modifying field behavior after initial authoring can result in backwards-incompatible changes in clients. For example, making an optional field required results in backwards-incompatible changes in the method signature of an RPC or a resource in a Declarative client. See the Backwards compatibility section for more detailed compatibility guidance.
Changelog
Section titled “Changelog”- 2024-04-17: Added initial guidance.
- 2025-09-06: Removal of the
IDENTIFIER
field. - 2025-10-11: Updated to use the new
aep.api.FieldBehavior
enum values withFIELD_BEHAVIOR_
prefix.